SSM项目集成Spring Security 4.X版本 之 加入DWZ,J-UI框架实现登录和主页菜单显示

目录

前言

一、加入DWZ J-UI框架

二、实现登录页面

三、实现主页面菜单显示


前言

大家好!写文章之前先列出几篇相关文章。本文内容也在其项目中接续实现。

一. SSM项目集成Spring Security 4.X版本(使用spring-security.xml 配置文件方式)_spring security4.x 会话管理配置文件版-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/u011529483/article/details/135699004?spm=1001.2014.3001.5501

二. SpringSecurity认证登录成功后获取角色菜单-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/u011529483/article/details/135763209?spm=1001.2014.3001.5501

三. Spring Security 4.X(XML文件配置session超时,单点登录-session并发控制,退出/logout)_spring security session过期时间 xml-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/u011529483/article/details/136043238?spm=1001.2014.3001.5501


一、加入DWZ J-UI框架

1. 下载DWZ J-UI框架并解压

https://download.csdn.net/download/u011529483/87930662

以上为个人下载地址。

2. 在项目中新建dwz文件,如下图:

然后将解压后的 J-UI 框架的内容全部拷贝到 dwz 文件夹中。我解压后的效果如下:

具体可以参考文章:记dwz(JUI)前端框架使用(一)_dwz框架-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/u011529483/article/details/129150062?spm=1001.2014.3001.5501

注意:此项目中由于加入了 spring-security ,所以需要对dwz文件夹进行配置,下图标红处:

好了!现在可以直接访问到 dwz 文件夹中的静态资源了。要复用dwz中的某一个页面只需要拷贝到指定位置修改成想要的模样就可以了。

二、实现登录页面

1. 将 dwz 文件夹中的 login.html 页面拷贝到 webapp 目录下,修改为jsp页面。如下图:

2. 修改 login.jsp 页面代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>wqxx系统登录页面</title>
    <link href="./dwz/themes/css/login.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="login">
    <div id="login_header">
        <h1 class="login_logo">
            <a href="#"><img src="./dwz/themes/default/images/login_logo.gif" /></a>
        </h1>
        <div class="login_headerContent">
            <div class="navList">
                <ul>
                    <li><a href="#">设为首页</a></li>
                    <li><a href="#">反馈</a></li>
                    <li><a href="./dwz/doc/dwz-user-guide.pdf" target="_blank">帮助</a></li>
                </ul>
            </div>
            <h2 class="login_title"><img src="./dwz/themes/default/images/login_title.png" /></h2>
        </div>
    </div>
    <div id="login_content">
        <div class="loginForm">
            <form action="${pageContext.request.contextPath}/spring_security_check" method="post">
                <p>
                    <label>用户名:</label>
                    <input type="text" name="username" size="20" class="login_input" />
                </p>
                <p>
                    <label>密码:</label>
                    <input type="password" name="password" size="20" class="login_input" />
                </p>
                <p>
                    <label>验证码:</label>
                    <input class="code" type="text" size="5" />
                    <span><img src="./dwz/themes/default/images/header_bg.png" alt="" width="75" height="24" /></span>
                </p>
                <div class="login_bar">
                    <input class="sub" type="submit" value=" " />
                </div>
            </form>
        </div>
        <div class="login_banner"><img src="./dwz/themes/default/images/login_banner.jpg" /></div>
        <div class="login_main">
            <div class="login_inner">
            </div>
        </div>
    </div>
    <div id="login_footer">
        Copyright &copy; 2009 www.dwzjs.com Inc. All Rights Reserved.
    </div>
</div>

</body>
</html>

主要注意 CSS, 图片等资源的路劲修改指向./dwz/目录中。

用户名,密码输入控件的修改与你的后台名称绑定。form表单提交请求的修改,因为使用了spring-security,所以提交路径为 spring-security.xml 文件中配置的路径

<form action="${pageContext.request.contextPath}/spring_security_check" method="post">

到此登录页面完成,如有页面显示差异,自己微调CSS等。运行项目效果如下:

另:附上 spring-security.xml 配置文件代码,登录的后台代码参考前言中的第一篇文章。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">

    <!--指定不受Spring Security管理-->
    <security:http security="none" pattern="/login" />
    <!--放行DWZ的静态资源-->
    <security:http security="none" pattern="/dwz/**" />
    <!--spring过滤器链配置
        1) 需要拦截什么资源
        2) 什么资源对应什么角色权限
        3) 定制认证方式: HttpBasic or FormLogin
        4) 自定义登录页面,定义登录请求地址,定义错误处理方式
    -->
    <security:http>

        <!--
            使用form-login的方式进行认证
                login-page:指定获取登录页面的url(需要编写controller返回登录页面)
                login-processing-url:指定登录页面中post请求提交到哪里的url(不需要编写controller,框架已实现)
                default-target-url:指定登录成功后,跳转到哪个url(需要编写controller)
                authentication-success-handler-ref:指定登录成功后,由哪个类来进行处理
                authentication-failure-handler-ref:指定登录失败后,由哪个类来进行处理
                username-parameter:指定登录表单中用户名的input中name值,如果这里不配置,则默认为username
                password-parameter:指定登录表单中密码的input中name值,如果这里不配置,则默认为password
        -->
        <security:form-login login-page="/login" login-processing-url="/spring_security_check"
                             authentication-success-handler-ref="myAuthenticationSuccessHandler"
                             authentication-failure-handler-ref="myAuthenticationFailureHandler"/>

        <!-- 关闭csrf的保护-->
        <security:csrf disabled="true"/>

        <!-- 配置资源拦截规则
            pattern属性指定资源目录: 即需要拦截的资源  /* 代表根目录下的一级目录  /** 代表根目录下的所有目录
            access(SpEL)方法执行Spring EL表达式。提供如下表达式:
                permitALL():设置那些路径可以直接访问,不需要认证。直接返回true
                isAnonymous():只有匿名用户可以访问,登录用户不可访问
                isAuthenticated():需要身份认证成功才能访问。如果认证用户不是匿名用户,则返回true,认证通过
                isFullyAuthenticated():需要身份认证成功才能访问。如果认证用户不是匿名用户或记住我的用户,则返回true,认证通过
                其它自行查找......
        -->
        <!--开始配置拦截规则,注意拦截规则的位置顺序(如不需要身份认证的规则,要放在前面,需要身份认证的规则放在后面)-->
        <!--permitAll()不需要身份认证,无条件放行-->
        <!--<security:intercept-url pattern="/login" access="permitAll()"/>-->
        <!--<security:intercept-url pattern="/system/index" access="permitAll()"/>-->
        <security:intercept-url pattern="/s_timeout.jsp" access="permitAll()"/>

        <!--进行权限划分:hasRole('ROLE_USER'):表示拥有 ROLE_USER 权限的用户可以访问
        hasRole('ROLE_ALL'):表示拥有 ROLE_ALL 权限的用户可以访问。指定特定权限访问
        -->
        <security:intercept-url pattern="/system/add" access="hasAuthority('admin')"/>
        <security:intercept-url pattern="/system/list" access="hasAuthority('ROLE_ALL')"/>

        <!--permitAll()不需要身份认证,无条件放行静态资源-->
        <security:intercept-url pattern="/js/**" access="permitAll()"/>

        <!--拦截所有页面,需要身份认证成功才能访问。如果认证用户不是匿名用户或记住我的用户,则返回true,认证通过-->
        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>
        <!--结束配置拦截规则-->

        <!-- 自定义用户访问权限不足的处理方式(需要编写controller返回权限不足的页面) -->
        <security:access-denied-handler error-page="/accessDeny"/>

        <!-- session管理,
        invalid-session-url:指定使用已经超时的sessionId(保存在Cookie中)进行请求需要重定向的页面或路径。
        max-sessions:默认值为1,session并发数量控制。控制同一用户在系统中同时允许存在的已经通过认证的session数量。当超过这个值时,
        Spring Security的默认策略是将先前的设为无效。如果要限制用户再次登录可以设置concurrency-control的error-if-maximum-exceeded的值为true。
        -->
        <security:session-management invalid-session-url="/s_timeout.jsp">
            <security:concurrency-control max-sessions="1" error-if-maximum-exceeded="false"/>
        </security:session-management>
        <!--<security:session-management session-authentication-error-url="/session" invalid-session-url="/session">
            <security:concurrency-control max-sessions="1" session-registry-alias="sessionRegistry" error-if-maximum-exceeded="false" expired-url="/session"/>
        </security:session-management>-->

        <!--加上Remember Me功能,token-validity-seconds:有效时间(秒)-->
        <!--<security:remember-me token-repository-ref="jdbcTokenRepository" token-validity-seconds="604800"/>-->

        <!--<security:logout/>:注销功能
        logout-url="/logout":退出过滤器默认的拦截路径,springSecurity内LogoutFilter要拦截的url(向这/logout发送请求来注销)
        logout-success-url:用户退出后要被重定向的url
        invalidate-session:默认为true,用户在退出后Http session失效
        success-handler-ref:指定一个bean(需要实现LogoutSuccessHandler接口),用来自定义退出成功后的操作
        delete-cookies="JSESSIONID":删除session对应的cookie
        -->
        <security:logout logout-url="/logout" logout-success-url="/login" invalidate-session="true" delete-cookies="JSESSIONID"/>
    </security:http>

    <!--身份验证管理器-->
    <security:authentication-manager>
        <!--
            自定义授权提供类MyUserDetailsService,获得登录用户的用户详情信息。此类实现UserDetailsService接口。
            user-service-ref="myUserDetailsService" : 指定 UserDetailsService 接口的实现类
            最终都要返回一个UserDetail,用户详情
        -->
        <security:authentication-provider user-service-ref="myUserDetailsService">
            <!-- 配置:加密算法对用户输入的密码进行加密,然后和数据库的密码进行配对 -->
            <!--<security:password-encoder ref="bCryptPasswordEncoder"/>-->
        </security:authentication-provider>
    </security:authentication-manager>

    <!--创建 springSecurity 密码加密工具类,使用PasswordEncoder 接口的实现,也可以使用别的-->
    <!--<bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>-->


    <!--springSecurity实现 remember me 功能:
        如果用户登录选择 remember me ,springSecurity会将其cookie值存入数据库,来实现remember me 功能
        JdbcTokenRepositoryImpl 用来存取cookie值-->
    <!--<bean id="jdbcTokenRepository" class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
        <property name="dataSource" ref="dataSource"/> &lt;!&ndash;数据库数据源&ndash;&gt;
        &lt;!&ndash;<property name="createTableOnStartup" value="true"/>&ndash;&gt; &lt;!&ndash;createTableOnStartup属性是当项目启动时,springSecurity创建表存储remember me相关信息,第二次启动时要注释这个属性&ndash;&gt;
    </bean>-->

</beans>

三、实现主页面菜单显示

1. 将 dwz 文件夹中的 index.html 页面拷贝到自定义项目目录 main 中,修改为 jsp页面,如下图:

2. 修改 index.jsp 页面代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>百炼成神管理系统</title>

    <link href="../dwz/themes/default/style.css" rel="stylesheet" type="text/css" media="screen"/>
    <link href="../dwz/themes/css/core.css" rel="stylesheet" type="text/css" media="screen"/>
    <link href="../dwz/themes/css/print.css" rel="stylesheet" type="text/css" media="print"/>
    <link href="../dwz/uploadify/css/uploadify.css" rel="stylesheet" type="text/css" media="screen"/>
    <!--[if IE]>
    <link href="../dwz/themes/css/ieHack.css" rel="stylesheet" type="text/css" media="screen"/>
    <![endif]-->

    <!--[if lt IE 9]><script src="../dwz/js/speedup.js" type="text/javascript"></script><script src="../dwz/js/jquery-1.12.4.js" type="text/javascript"></script><![endif]-->
    <!--[if gte IE 9]><!--><script src="../dwz/js/jquery-3.4.1.js" type="text/javascript"></script><!--<![endif]-->

    <script src="../dwz/js/jquery.cookie.js" type="text/javascript"></script>
    <script src="../dwz/js/jquery.validate.js" type="text/javascript"></script>
    <!--<script src="js/jquery.bgiframe.js" type="text/javascript"></script>-->
    <script src="../dwz/xheditor/xheditor-1.2.2.min.js" type="text/javascript"></script>
    <script src="../dwz/xheditor/xheditor_lang/zh-cn.js" type="text/javascript"></script>
    <script src="../dwz/uploadify/scripts/jquery.uploadify.js" type="text/javascript"></script>

    <script type="text/javascript" src="../dwz/chart/echarts.min.js"></script>

    <script src="../dwz/js/dwz.core.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.util.date.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.validate.method.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.barDrag.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.drag.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.tree.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.accordion.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.ui.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.theme.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.switchEnv.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.alertMsg.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.contextmenu.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.navTab.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.tab.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.resize.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.dialog.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.dialogDrag.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.sortDrag.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.cssTable.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.stable.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.taskBar.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.ajax.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.pagination.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.database.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.selectedLoad.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.datepicker.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.effects.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.panel.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.checkbox.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.history.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.combox.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.file.js" type="text/javascript"></script>
    <script src="../dwz/js/dwz.print.js" type="text/javascript"></script>

    <!-- 可以用dwz.min.js替换前面全部dwz.*.js (注意:替换时下面dwz.regional.zh.js还需要引入)
    <script src="bin/dwz.min.js" type="text/javascript"></script>
    -->
    <script src="../dwz/js/dwz.regional.zh.js" type="text/javascript"></script>

    <script type="text/javascript">
        $(function(){
            DWZ.init("../dwz/dwz.frag.xml", {
                loginUrl:"../dwz/login_dialog.html", loginTitle:"登录",	// 弹出登录对话框
//		loginUrl:"login.html",	// 跳到登录页面
                statusCode:{ok:200, error:300, timeout:301}, //【可选】
                pageInfo:{pageNum:"pageNum", numPerPage:"numPerPage", orderField:"orderField", orderDirection:"orderDirection"}, //【可选】
                keys: {statusCode:"statusCode", message:"message"}, //【可选】
                ui:{hideMode:'offsets'}, //【可选】hideMode:navTab组件切换的隐藏方式,支持的值有’display’,’offsets’负数偏移位置的值,默认值为’display’
                debug:false,	// 调试模式 【true|false】
                callback:function(){
                    initEnv();
                    $("#themeList").theme({themeBase:"themes"}); // themeBase 相对于index页面的主题base路径
                }
            });
        });

    </script>

</head>

<body>
<div id="layout">
    <div id="header">
        <div class="headerNav">
            <a class="logo" href="#">标志</a>
            <ul class="nav">
                <li id="switchEnvBox"><a href="javascript:">(<span>北京</span>)切换城市</a>
                    <ul>
                        <li><a href="../dwz/sidebar_1.html">北京</a></li>
                        <li><a href="../dwz/sidebar_2.html">上海</a></li>
                        <li><a href="../dwz/sidebar_2.html">南京</a></li>
                        <li><a href="../dwz/sidebar_2.html">深圳</a></li>
                        <li><a href="../dwz/sidebar_2.html">广州</a></li>
                        <li><a href="../dwz/sidebar_2.html">天津</a></li>
                        <li><a href="../dwz/sidebar_2.html">杭州</a></li>
                    </ul>
                </li>
                <li><a href="../dwz/changepwd.html" target="dialog" rel="changepwd" width="600">设置</a></li>
                <li><a href="<c:url value='/logout'/>">退出系统</a></li>

            </ul>
            <ul class="themeList" id="themeList">
                <li theme="default"><div class="selected">蓝色</div></li>
                <li theme="green"><div>绿色</div></li>
                <!--<li theme="red"><div>红色</div></li>-->
                <li theme="purple"><div>紫色</div></li>
                <li theme="silver"><div>银色</div></li>
                <li theme="azure"><div>天蓝</div></li>
            </ul>
        </div>

        <!-- navMenu -->

    </div>

    <div id="leftside">
        <div id="sidebar_s">
            <div class="collapse">
                <div class="toggleCollapse"><div></div></div>
            </div>
        </div>
        <div id="sidebar">
            <div class="toggleCollapse"><h2>主菜单界面</h2><div>收缩</div></div>

            <div class="accordion" fillSpace="sidebar">
                <div class="accordionHeader">
                    <h2><span>Folder</span>导航列表</h2>
                </div>
                <div class="accordionContent">

                    <ul class="tree treeFolder">
                    <!-- 菜单开始 -->
                        <c:choose>
                            <c:when test="${listMenu.size()>0}">
                                    <c:forEach var="lstMenu" items="${listMenu}" varStatus="status">
                                        <c:if test="${lstMenu.parentId eq 10000}">
                                            <li><a href="${lstMenu.url}" target="navTab">${lstMenu.name}</a>

                                                <c:forEach var="menuChild" items="${listMenu}">
                                                    <c:if test="${menuChild.parentId eq lstMenu.id}">
                                                        <ul>
                                                            <li><a href="${menuChild.url}" target="navTab" rel="page1" fresh="false">${menuChild.name}</a></li>
                                                        </ul>
                                                    </c:if>
                                                </c:forEach>
                                            </li>
                                        </c:if>
                                    </c:forEach>
                            </c:when>
                            <c:otherwise>
                                <p>没有查询到菜单列表!</p>
                            </c:otherwise>
                        </c:choose>
                    <!-- 菜单结束 -->
                    </ul>
                </div>
            </div>
        </div>
    </div>
    <div id="container">
        <div id="navTab" class="tabsPage">
            <div class="tabsPageHeader">
                <div class="tabsPageHeaderContent"><!-- 显示左右控制时添加 class="tabsPageHeaderMargin" -->
                    <ul class="navTab-tab">
                        <li tabid="main" class="main"><a href="javascript:;"><span><span class="home_icon">我的主页</span></span></a></li>
                    </ul>
                </div>
                <div class="tabsLeft">left</div><!-- 禁用只需要添加一个样式 class="tabsLeft tabsLeftDisabled" -->
                <div class="tabsRight">right</div><!-- 禁用只需要添加一个样式 class="tabsRight tabsRightDisabled" -->
                <div class="tabsMore">more</div>
            </div>
            <ul class="tabsMoreList">
                <li><a href="javascript:;">我的主页</a></li>
            </ul>
            <div class="navTab-panel tabsPageContent layoutBox">
                <div class="page unitBox">

                    <div class="pageFormContent" layoutH="80" style="margin-right:230px">

                    </div>

<%--                    <div style="width:230px;position: absolute;top:60px;right:0" layoutH="80">
                        <iframe width="100%" height="430" class="share_self" frameborder="0" scrolling="no" src="//widget.weibo.com/weiboshow/index.php?width=0&height=430&fansRow=2&ptype=1&skin=1&isTitle=0&noborder=1&isWeibo=1&isFans=0&uid=1739071261&verifier=c683dfe7"></iframe>
                    </div>--%>
                </div>

            </div>
        </div>
    </div>

</div>

<div id="footer">Copyright &copy; 2020 <a href="demo_page2.html" target="dialog">DWZ团队</a> 京ICP备15053290号-2</div>

</body>
</html>

主要引入JSP页面需要的标签库,修改所有dwz静态资源的访问路径。其它用不到的代码直接删除掉即可,如下图:

到此基本的主页修改完成,现在我们来动态显示后台请求到的菜单。将index.jsp页面的菜单部分多余代码删除,然后替换为下图代码:

动态菜单必须通过后台请求查询得到,所以此时我们修改spring-security.xml文件中登录成功后的处理类MyAuthenticationSuccessHandler 的逻辑,即保存登录用户信息后重定向到Controller的./system/index请求,代码如下:

另:注释掉spring-security.xml文件中/system/index请求路径的放行配置,即需要身份认证成功才能访问。

package com.wqbr.wqdemotwo.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wqbr.wqdemotwo.domain.SysUser;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Service;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * 登录成功后的处理类
 * @author lv
 * @date 2024年1月16日
 */
@Service
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    // new 一个 jackson 的 对象
    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 此方法会在登录成功后进行回调
     *
     * @param authentication:表示认证成功后的信息
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        System.out.println("********* onAuthenticationSuccess");
        HttpSession session = request.getSession();
        System.out.println("session对象:"+session);
        System.out.println("----session.getId():"+session.getId());
        System.out.println("*****session.isNew():"+session.isNew());
        try {
            SysUser user = (SysUser) authentication.getPrincipal();
            session.setAttribute("loginInfo", user);
            response.sendRedirect("./system/index"); //重定向到Controller中指定的路径
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

​​​​​​​SystemController类中的index方法代码修改如下(即./system/index请求的方法):

    @RequestMapping(path = "/index")
    public ModelAndView index(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        System.out.println("session对象:" + session);
        System.out.println("----session.getId():" + session.getId());
        System.out.println("*****session.isNew():" + session.isNew());
        System.out.println("index 页面进入......");

        ModelAndView model = new ModelAndView("main/index");
        SysUser user = (SysUser) authentication.getPrincipal();
        String username = user.getUsername();
        if (username != null) {
            List<Menus> listMenu = new ArrayList<>();
            List<SysPermission> pList = systemService.findPermissionByUsername(username);
            System.out.println("=-----=大小为:" + pList.size());
            for (SysPermission permission : pList) {
                if (permission.getResource_type().equals("menu")) {
                    Menus menu = new Menus();
                    menu.setId(Long.parseLong(permission.getId()));
                    menu.setName(permission.getName());
                    menu.setParentId(Long.parseLong(permission.getParent_id()));
                    menu.setParentIds(Long.parseLong(permission.getParent_ids()));
                    menu.setUrl(permission.getUrl());
                    listMenu.add(menu);
                }
            }
            model.addObject("listMenu", listMenu);
        }
        return model;
    }

spring-security认证登录成功后获取菜单资源的实现可具体参考前言提到的第二篇文章。

到此已经可以实现登录后获取主页左边的动态菜单显示了,运行项目登录后显示效果如下:

好了,此文章的码字就到此结束了,再见

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/408206.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

旅游组团自驾游拼团系统 微信小程序python+java+node.js+php

随着社会的发展&#xff0c;旅游业已成为全球经济中发展势头最强劲和规模最大的产业之一。为方便驴友出行&#xff0c;寻找旅游伙伴&#xff0c;更好的规划旅游计划&#xff0c;开发一款自驾游拼团小程序&#xff0c;通过微信小程序发起自驾游拼团&#xff0c;吸收有车或无车驴…

CentOS安装Redis教程

CentOS安装Redis教程 一、Redis安装包压缩文件下载二、把下载好的Redis安装包压缩文件上传到服务器三、Redis安装四、Redis相关配置五、运行redis并指定配置文件 一、Redis安装包压缩文件下载 下载地址&#xff1a;Redis官网 省事链接奉上&#xff1a;Redis 6.2.14网盘下载链接…

在Linux服务器上部署一个单机项目

目录 一、jdk安装 二、tomcat安装 三、MySQL安装 四、部署项目 一、jdk安装 1. 上传jdk安装包 jdk-8u151-linux-x64.tar.gz 进入opt目录&#xff0c;将安装包拖进去 2. 解压安装包 这里需要解压到usr/local目录下&#xff0c;在这里我新建一个文件夹保存解压后的文件 [r…

ElasticSearch语法

Elasticsearch 概念 入门学习: Index索引>MySQL 里的表(table)建表、增删改查(查询需要花费的学习时间最多)用客户端去调用 ElasticSearch(3 种)语法:SQL、代码的方法(4 种语法) ES 相比于 MySQL&#xff0c;能够自动帮我们做分词&#xff0c;能够非常高效、灵活地查询内…

5.2.鸿蒙LiteOS-M los_dispatch

目录 一、cortex-m4 los_dispatch.S代码分析坚持就有收获 一、cortex-m4 los_dispatch.S代码分析 .syntax unified #.syntax [unified | divided], 指定arm 汇编语法规则 .arch armv7e-m #指定平台, 与命令行参数-march同样的作用 .fpu fpv4-sp-d16 #指定浮点运算…

第九篇【传奇开心果系列】python文本和语音相互转换库技术点案例示例:SpeechRecognitio库开发会议记录和转录工具经典案例

传奇开心果博文系列 系列博文目录python文本和语音相互转换库技术点案例示例系列 博文目录前言一、雏形示例代码二、扩展思路介绍三、SpeechRecognition库多种语音识别引擎支持示例代码四、SpeechRecognition库实时语音转录示例代码五、SpeechRecognitio库转录文本中提取关键词…

GPT Pilot - 编写 95% 代码的开发工具!

在这篇博客介绍了GPT-pilot的研发细节&#xff0c;原作者将探讨GPT Pilot的技术内核 —— 一款基于GPT-4编写的开发工具&#xff0c;可以生成生产使用代码的应用。 你有没有想过&#xff0c;95%的应用代码&#xff0c;可以由AI编写&#xff0c;就像《钢铁侠》里的贾维斯一样&a…

DAY30--learning English

一、积累 1.budget 2.fabulous 3.strait 4.jut 5.grater 6.fillet 7.fin 8.decay 9.cartilage 10.gill 11.convex 12.concave 13.tender 14.trim 15.workload 16.knuckle 17.crevice 18.skew 19.membrane 20.delicate 二、练习 1.牛津原译 Budget /ˈbʌdʒɪt/ 1.[ CU]the…

一流的财务:搞数据!!!(干货)

“三流财务给数据&#xff0c;二流财务给分析报告&#xff0c;一流财务给....&#xff08;解决方案&#xff09;“这些文章应该很多人都看到过&#xff0c;这个口号粗看好像很有道理&#xff0c;但笔者并不认同&#xff0c;因为大家都忽略了一个重要的概念&#xff1a;数据&…

CrossOver2024国产版虚拟机软件有哪些功能呢?

除了办公应用场景&#xff0c;CrossOver虚拟机软件还可以在以下场景中使用&#xff1a; 设计与开发&#xff1a;对于设计师和开发人员来说&#xff0c;某些特定的Windows设计和开发工具可能在Mac或Linux上没有完美的替代品。此时&#xff0c;他们可以使用CrossOver来运行这些工…

SQL 中如何实现多表关联查询?

阅读本文之前请参阅----MySQL 数据库安装教程详解&#xff08;linux系统和windows系统&#xff09; 在SQL中&#xff0c;多表关联查询是通过使用JOIN操作来实现的&#xff0c;它允许你从两个或多个表中根据相关列的值来检索数据。以下是几种常见的JOIN类型&#xff1a; …

wpf 3d 后台加载模型和调整参数

下载了一个代码&#xff0c;加载obj模型&#xff1b;它的参数在xaml里&#xff0c;模型加载出来刚好&#xff1b; 然后加载另一个obj模型&#xff1b;加载出来之后大&#xff0c;偏到很高和左的位置&#xff1b; 它之前的摄像机位置&#xff0c; Position"9.94759830064…

Apache celeborn 安装及使用教程

1.下载安装包 https://celeborn.apache.org/download/ 测0.4.0时出现https://github.com/apache/incubator-celeborn/issues/835 2.解压 tar -xzvf apache-celeborn-0.3.2-incubating-bin.tgz 3.修改配置文件 cp celeborn-env.sh.template celeborn-env.shcp log4j2.xml.…

Canvas学习笔记02:canvas的路径扫盲,附代码案例

hello&#xff0c;我是贝格前端工场&#xff0c;最近在学习canvas&#xff0c;分享一些canvas的一些知识点笔记&#xff0c;本期分享canvas的路径知识&#xff0c;欢迎老铁们一同学习&#xff0c;欢迎关注&#xff0c;如有前端项目可以私信贝格。 一、什么是canvas路径 Canvas…

滑动窗口刷题(三)

1. 找到字符串中所有字母异位词 1.题目解析 比较易懂&#xff0c;不做解析。 2.算法思路 哈希表滑动窗口有效字符个数优化 创建两个哈希表&#xff0c;将p字符串存入哈希表2。 定义cnt存放有效字符个数。 进窗口&#xff1a;存入哈希表1&#xff0c;如果该元素在哈希1中的…

嵌入式中常见语言对内存管理基本方法

大家好&#xff0c;今天给大家分享一下&#xff0c;从语言角度来讲:对比常见的几种语言对内存的管理方法​。 (1&#xff09;汇编语言:根本没有任何内存管理&#xff0c;内存管理全靠程序员自己&#xff0c;汇编中操作内存时直接使用内存地址&#xff08;譬如0xd0020010 )&…

前端工程化面试题 | 17.精选前端工程化高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

ElasticSearch索引数据备份与恢复

索引数据备份 在磁盘创建备份目录并授权 # 创建备份目录 /home/esbackup # 授权 chmod 777 /home/esbackup修改配置文件elasticsearch.yml echo path.repo: ["/home/esbackup"] >> /etc/elasticsearch/elasticsearch.yml重启elasticsearch(我是docker创建的…

python:读 Freeplane.mm文件,使用 xml.etree 生成测试案例.csv文件

Freeplane 是一款基于 Java 的开源软件&#xff0c;继承 Freemind 的思维导图工具软件&#xff0c;它扩展了知识管理功能&#xff0c;在 Freemind 上增加了一些额外的功能&#xff0c;比如数学公式、节点属性面板等。 强大的节点功能&#xff0c;不仅仅节点的种类很多&#xf…

提升代码能力:程序员的进阶之路

提升代码能力&#xff1a;程序员的进阶之路 在当今日益发展的技术领域&#xff0c;程序员的代码能力对于个人职业发展至关重要。优秀的代码能力不仅能提高开发效率&#xff0c;还能产生高质量的软件和解决方案。然而&#xff0c;提升代码能力是一个不断学习和成长的过程。本文将…