SpringSecurity认证登录成功后获取角色菜单

目录

前言

一、RBAC模型

二、实战应用

1. 建立用户、角色、资源实体类

2. 数据层查询角色资源

3. 业务层实现,调用数据层查询接口

4. SystemController控制器菜单获取方法

5. menu.jsp菜单页面实现


前言

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

文章之后,代码在同一个示例工程中。如有必要请参考此文。


一、RBAC模型

本文获取菜单资源是基于角色分配的方式获得的。即什么用户是什么样的角色,什么角色可以访问什么资源。也就是RBAC模型(Role-Based Access Control:基于角色的访问控制)。RBAC模型的3个基础组成部分便是:用户、角色和权限。

  • User(用户):用户有唯一的ID,分配到不同的角色上
  • Role(角色):角色有唯一的ID,角色分配有不同的权限(资源)
  • Permission(权限):资源有唯一的ID,系统的访问权限(资源)
  • 用户-角色映射:用户和角色建立对应关系。用户表ID对应角色表ID
  • 角色-权限映射:角色和权限(资源)建立对应关系。角色表ID对应资源表ID

二、实战应用

1. 建立用户、角色、资源实体类

package com.wqbr.domain;import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;/*** 系统用户,封装用户数据,实现 UserDetails 接口* @author lv* @date 2024年1月11日*/
public class SysUser implements UserDetails {private static final long serialVersionUID = 1L;private String id;private String username; //从UserDetails的重写方法中返回private String password; //从UserDetails的重写方法中返回private Date addtime;private boolean accountnonexpired; //账户是否过期,从UserDetails的重写方法中返回private boolean accountnonlocked; //账户是否锁定,从UserDetails的重写方法中返回private boolean credentialsnonexpired; //密码是否过期,从UserDetails的重写方法中返回private boolean enabled; //账户是否可用,从UserDetails的重写方法中返回// 储存用户拥有的所有权限private List<GrantedAuthority> authorities = new ArrayList<>(); //从UserDetails的重写方法中返回public String getId() {return id;}public void setId(String id) {this.id = id;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}public Date getAddtime() {return addtime;}public void setAddtime(Date addtime) {this.addtime = addtime;}// 返回用户权限,上面声明了权限集合对象 authorities@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return this.authorities;}public void setAuthorities(List<GrantedAuthority> authorities) {this.authorities = authorities;}// 返回用户密码,上面声明了属性 password@Overridepublic String getPassword() {return password;}// 返回用户名,上面声明了属性 username@Overridepublic String getUsername() {return username;}@Overridepublic boolean isAccountNonExpired() {return accountnonexpired;}public void setAccountnonexpired(boolean accountnonexpired) {this.accountnonexpired = accountnonexpired;}@Overridepublic boolean isAccountNonLocked() {return accountnonlocked;}public void setAccountnonlocked(boolean accountnonlocked) {this.accountnonlocked = accountnonlocked;}@Overridepublic boolean isCredentialsNonExpired() {return credentialsnonexpired;}public void setCredentialsnonexpired(boolean credentialsnonexpired) {this.credentialsnonexpired = credentialsnonexpired;}@Overridepublic boolean isEnabled() {return enabled;}public void setEnabled(boolean enabled) {this.enabled = enabled;}
}
package com.wqbr.domain;/*** 系统角色* @author lv* @date 2024年1月16日*/
public class SysRole {private String id;private String available;private String description;private String role;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getAvailable() {return available;}public void setAvailable(String available) {this.available = available;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public String getRole() {return role;}public void setRole(String role) {this.role = role;}}
package com.wqbr.domain;/*** 系统资源* @author lv* @date 2024年1月16日*/
public class SysPermission {private String id;private String available;private String name;private String parent_id;private String parent_ids;private String permission;private String resource_type;private String url;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getAvailable() {return available;}public void setAvailable(String available) {this.available = available;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getParent_id() {return parent_id;}public void setParent_id(String parent_id) {this.parent_id = parent_id;}public String getParent_ids() {return parent_ids;}public void setParent_ids(String parent_ids) {this.parent_ids = parent_ids;}public String getPermission() {return permission;}public void setPermission(String permission) {this.permission = permission;}public String getResource_type() {return resource_type;}public void setResource_type(String resource_type) {this.resource_type = resource_type;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}}

关于这3个表的建表语句,数据插入语句请参考此文(数据库oracle)spirng框架之spring security(二)insert 语句补充-CSDN博客

2. 数据层查询角色资源

定义SystemDao接口类的查询方法

    /*** 查询当前用户拥有的资源*/public List<SysPermission> findPermissionByUsername(String username);

SystemDao.xml(mybatis的mapper文件)查询语句

    <!--查询当前用户拥有的资源--><select id="findPermissionByUsername" parameterType="String" resultType="com.wqbr.domain.SysPermission">select d.*from sys_user a, sys_user_role b, sys_role_permission c, sys_permission dwhere a.id = b.user_id and b.role_id = c.role_id and c.permission_id = d.idand a.username = #{username}</select>

3. 业务层实现,调用数据层查询接口

package com.wqbr.service;import com.wqbr.domain.SysPermission;import java.util.List;/*** 系统服务接口* @author lv* @date 2024年1月11日*/
public interface SystemService {/*** 查询当前用户拥有的资源*/public List<SysPermission> findPermissionByUsername(String username);
}
package com.wqbr.service.impl;import com.wqbr.domain.SysPermission;
import com.wqbr.persistence.SystemDao;
import com.wqbr.service.SystemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;/*** 系统服务接口实现* @author lv* @date 2024年1月11日*/
@Service
public class SystemServiceImpl implements SystemService {@Autowiredprivate SystemDao systemDao;@Overridepublic List<SysPermission> findPermissionByUsername(String username) {return systemDao.findPermissionByUsername(username);}
}

4. SystemController控制器菜单获取方法

先新建一个菜单数据装载实体类Menus

package com.wqbr.domain;/*** 定义的实体类,保存菜单数据*/
public class Menus {private long id;private String name;private Long parentId;private Long parentIds;private String url;public long getId() {return id;}public void setId(long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Long getParentId() {return parentId;}public void setParentId(Long parentId) {this.parentId = parentId;}public Long getParentIds() {return parentIds;}public void setParentIds(Long parentIds) {this.parentIds = parentIds;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}
}

SystemController类中的方法

    @GetMapping("/findMenu")public ModelAndView findMenus(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {ModelAndView model = new ModelAndView("main/menu");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);}}//request.setAttribute("listMenus", listMenu);model.addObject("listMenu",listMenu);//            for (Menus menus : listMenu) {
//                if (menus.getParentId() == 10000) { //10000为数据库中的值
//                    System.out.println("==" + menus.getName() + "[" + menus.getUrl() + "]");
//                    for (Menus menusch : listMenu) {
//                        if (menus.getId() == menusch.getParentId()) {
//                            System.out.println("---------" + menusch.getName() + "[" + menusch.getUrl() + "]");
//                        }
//                    }
//                }
//            }}return model;}

到此已经可以运行项目,登录成功后在浏览器地址栏调用控制器的 /findMenu 请求在控制台打印出菜单结构。

5. menu.jsp菜单页面实现

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<html>
<head><title>菜单列表</title>
</head>
<body>
<div><h2>导航菜单</h2></div>
<!-- 菜单开始 -->
<div><h4>列表大小:${listMenu.size()}</h4><c:choose><c:when test="${listMenu.size()>0}"><dl><c:forEach var="lstMenu" items="${listMenu}" varStatus="status"><c:if test="${lstMenu.parentId eq 10000}"><dt style="height: 28px;"><span>■</span><span onclick="alert('■父菜单${status.index}')">${lstMenu.name}</span>:<span>${lstMenu.url}</span></dt><c:forEach var="menuChild" items="${listMenu}"><c:if test="${menuChild.parentId eq lstMenu.id}"><dd style="height: 25px;"><span>●</span><span onclick="alert('●子菜单${status.index}')">${menuChild.name}</span>:<span>${menuChild.url}</span></dd></c:if></c:forEach></c:if></c:forEach></dl></c:when><c:otherwise><p>没有查询到菜单列表!</p></c:otherwise></c:choose>
</div>
<!-- 菜单结束 -->
</body>
</html>

菜单页面实现结束,现在运行项目查看页面效果。

登录成功后浏览器输入:http://localhost:8080/wqdemotwo_war/system/findMenu

用户表中有两个用户:

zhangsan用户登录成功后的菜单资源:

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决TortoiseGit软件Git Show log时显示Too many files to display的问题

1 问题描述 有时代码提交修改的文件比较多&#xff0c;当查看log时无法显示出来修改的文件列表&#xff0c;如下所示&#xff1a; 2 解决方法 将LogTooManyItemsThreshold尽可能配置得大一些。 三 参考资料 https://gitlab.com/tortoisegit/tortoisegit/-/issues/3878

常用通信总线学习——RS232与RS485

RS232概述 RS-232标准接口&#xff08;又称EIA RS-232&#xff09;是常用的串行通信接口标准之一&#xff0c;它是由美国电子工业协会(Electronic Industry Association&#xff0c;EIA)联合贝尔系统公司、调制解调器厂家及计算机终端生产厂家于1970年共同制定&#xff0c;其全…

C++核心编程:C++ 中的引用 笔记

2.引用 2.1 引用的基本使用 - 作用&#xff1a;给变量起别名 - 语法&#xff1a;数据类型 &别名 原名 #include<iostream> using namespace std; int main() {// 引用基本语法// 数据类型 &别名 原名int a 10;// 创建引用int &ref_a a;cout<<&qu…

快速入门Playwright框架:从零到自动化测试的第一步

Playwright框架&#xff1a; 背景介绍&#xff1a; ​ Playwright 是微软开发的 Web应用 的 自动化测试框架 。selenium相对于Playwright慢很多&#xff0c;因为Playwright是异步实现的&#xff0c;但是selenium是同步的&#xff0c;就是后一个操作必须等待前一个操作。 sel…

代码随想录 Leetcode226.翻转二叉树

题目&#xff1a; 代码(首刷看解析 2024年1月25日&#xff09;&#xff1a; class Solution { public:TreeNode* invertTree(TreeNode* root) {if(root nullptr) return root;swap(root->left,root->right);invertTree(root->left);invertTree(root->right);retu…

【ARMv8M Cortex-M33 系列 7 -- RA4M2 移植 RT-Thread 问题总结】

请阅读【嵌入式开发学习必备专栏 】 文章目录 问题小结栈未对齐 经过几天的调试&#xff0c;成功将rt-thead 移植到 RA4M2&#xff08;Cortex-M33 核&#xff09;上&#xff0c;thread 和 shell 命令已经都成功支持。 问题小结 在完成 rt-thread 代码 Makefile 编译系统搭建…

基于LSTM的负荷预测,基于BILSTM的负荷预测,基于GRU的负荷预测,基于BIGRU的负荷预测,基于BP神经网络的负荷预测

目录 背影 摘要 代码和数据下载&#xff1a;基于LSTM的负荷预测&#xff0c;基于BILSTM的负荷预测&#xff0c;基于GRU的负荷预测&#xff0c;基于BIGRU的负荷预测&#xff0c;基于BP神经网络的负荷预测资源-CSDN文库 https://download.csdn.net/download/abc991835105/8876806…

leetcode 第三弹

链表声明&#xff1a; * Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(n…

操作系统-进程通信(共享存储 消息传递 管道通信 读写管道的条件)

文章目录 什么是进程通信为什么进程通信需要操作系统支持共享存储消息传递直接通信方式间接通信方式 管道通信小结注意 什么是进程通信 分享吃瓜文涉及到了进程通信 进程通信需要操作系统支持 为什么进程通信需要操作系统支持 进程不能访问非本进程的空间 当进程P和Q需要…

【学网攻】 第(5)节 -- Cisco VTP的使用

文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻】 第(2)节 -- 交换机认识及使用【学网攻】 第(3)节 -- 交换机配置聚合端口【学网攻】 第(4)节 -- 交换机划分Vlan 前言 网络已经成为了我们生活中不可或缺的一部分&#xff0c;它连接了世界各地的人们&#xff0c;让信息和资…

InitVerse:为云计算服务带来更高的透明度和可验证性

InitVerse&#xff1a;为云计算服务带来更高的透明度和可验证性 在云计算服务领域&#xff0c;透明度和可验证性是构建信任的关键要素。传统的云计算市场往往缺乏透明度&#xff0c;用户难以了解其数据和计算资源的实际使用情况。然而&#xff0c;通过利用区块链技术&#xff0…

简单快速取消AlertDialog的白色背景框,AlertDialog设置圆角背景

问题描述&#xff1a; 产品需求弹出的提示框是圆角&#xff0c;使用shape 设置圆角背景后&#xff0c;弹出的AlertDialog提示框四个角有白色的背景&#xff0c;据分析这个背景是 AlertDialog 父组件的背景色。 解决方法&#xff1a; 将Dialog的背景设置为透明色&#xff0c;代…

基于 Hologres+Flink 的曹操出行实时数仓建设

云布道师 曹操出行创立于 2015 年 5 月 21 日&#xff0c;是吉利控股集团布局“新能源汽车共享生态”的战略性投资业务&#xff0c;以“科技重塑绿色共享出行”为使命&#xff0c;将全球领先的互联网、车联网、自动驾驶技术以及新能源科技&#xff0c;创新应用于共享出行领域&…

【K8S 云原生】K8S的安全机制

目录 一、K8S安全机制概述 1、概念 2、请求apiserver资源的三个步骤&#xff1a; 一、认证&#xff1a;Anthentcation 1、认证的方式&#xff1a; 1、HTTP TOKEN&#xff1a; 2、http base&#xff1a; 3、http证书&#xff1a; 2、认证的访问类型&#xff1a; 3、签发…

Fluent Bit配置与使用——基于版本V2.2.2

Fluent Bit日志采集终端 文档适用版本&#xff1a;V2.2 1、日志文件处理流程 数据源是一个普通文件&#xff0c;其中包含 JSON 内容&#xff0c;使用tail插件记录日志&#xff0c;通过parsers进行格式化匹配&#xff08;图里没写&#xff09;&#xff0c;通过两个筛选器&…

VR数字展厅,平面静态跨越到3D立体化时代

近些年&#xff0c;VR的概念被越来越多的人提起&#xff0c;较为常见的形式就是VR数字展厅。VR数字展厅的出现&#xff0c;让各地以及各行业的展厅展馆的呈现和宣传都发生了很大的改变和革新&#xff0c;同时也意味着展览传播的方式不再局限于原来的图文、视频&#xff0c;而是…

2024年新提出的算法:一种新的基于数学的优化算法——牛顿-拉夫森优化算法|Newton-Raphson-based optimizer,NRBO

1、简介 开发了一种新的元启发式算法——Newton-Raphson-Based优化器&#xff08;NRBO&#xff09;。NRBO受到Newton-Raphson方法的启发&#xff0c;它使用两个规则&#xff1a;Newton-Raphson搜索规则&#xff08;NRSR&#xff09;和Trap Avoidance算子&#xff08;TAO&#…

花式沉默Defender

编者注&#xff1a;本文仅供学习研究&#xff0c;严禁从事非法活动&#xff0c;任何后果由使用者本人负责。 前言 总结了一下现在还能用的关闭Defender的方法&#xff0c;部分是原创&#xff0c;一部分借鉴的大佬。觉得字多的同学可以直接跳过思路查看步骤进行实操。 修改注册…

Git Docker 学习笔记

注意&#xff1a;该文章摘抄之百度&#xff0c;仅当做学习笔记供小白使用&#xff0c;若侵权请联系删除&#xff01; 目录 列举工作中常用的几个git命令&#xff1f; 提交时发生冲突&#xff0c;你能解释冲突是如何产生的吗&#xff1f;你是如何解决的&#xff1f; git的4个…

腾讯云轻量应用Windows服务器如何搭建幻兽帕鲁Palworld私服?

幻兽帕鲁/Palworld是一款2024年Pocketpair开发的开放世界生存制作游戏&#xff0c;在帕鲁的世界&#xff0c;玩家可以选择与神奇的生物“帕鲁”一同享受悠闲的生活&#xff0c;也可以投身于与偷猎者进行生死搏斗的冒险。而帕鲁可以进行战斗、繁殖、协助玩家做农活&#xff0c;也…