Spring Security-动态权限控制(1)

Spring Security-动态权限控制(1)_第1张图片

SpringSecurity过滤器链,图中绿色的是认证相关的,蓝色部分是异常相关的,而橙色部分是授权相关,今天我们就是要理清橙色部分授权相关的流程,以及实现动态授权。

整个动态授权的过程

Spring Security-动态权限控制(1)_第2张图片

通过上面的授权流程分析,咱们大致清楚了SpringSecurity是怎么授权的,那么我们要实现动态授权应该怎么做?其实就是实现自定义上图中的两个类:一个是SecurityMetadataSource类用来获取当前请求所需要的权限;另一个是AccessDecisionManager类来实现授权决策

Spring Security-动态权限控制(1)_第3张图片

FilterInvocationSecurityMetadataSource:通过此类,获取哪些角色可以访问该 url 。

AccessDecisionManager:通过此类,判断用户时候拥有上述中的角色。

Spring Security-动态权限控制(1)_第4张图片

因为要实现 动态 基于路径的权限管理, 因此 需要 数据库的支持

Spring Security-动态权限控制(1)_第5张图片

项目目录结构

Spring Security-动态权限控制(1)_第6张图片

1.建表

数据库 设计 共 5张表

 menu表
 DROP TABLE IF EXISTS `menu`;
 CREATE TABLE `menu`  (
   `id` int(0) NOT NULL AUTO_INCREMENT,
   `pattern` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
   PRIMARY KEY (`id`) USING BTREE
 ) 
 ​插入数据
 INSERT INTO `menu` VALUES (1, '/test/add');
 INSERT INTO `menu` VALUES (2, '/test/export');
 INSERT INTO `menu` VALUES (3, '/test/update');
 INSERT INTO `menu` VALUES (4, '/test/delete');
 INSERT INTO `menu` VALUES (5, '/test/query');
 INSERT INTO `menu` VALUES (6, '/test/toLogin');
role 角色表
 DROP TABLE IF EXISTS `role`;
 CREATE TABLE `role`  (
   `id` int(0) NOT NULL AUTO_INCREMENT,
   `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
   `nameZh` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
   PRIMARY KEY (`id`) USING BTREE
 )
 ​
角色表数据
 INSERT INTO `role` VALUES (1, 'ROLE_admin', '系统管理员');
 INSERT INTO `role` VALUES (2, 'ROLE_user', '普通用户');
 ​
 ​
 ​ role_menu   角色与菜单 表
 CREATE TABLE `role_menu`  (
   `id` int(0) NOT NULL AUTO_INCREMENT,
   `mid` int(0) NULL DEFAULT NULL,
   `rid` int(0) NULL DEFAULT NULL,
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `mid`(`mid`) USING BTREE,
   INDEX `rid`(`rid`) USING BTREE,
   CONSTRAINT `role_menu_ibfk_1` FOREIGN KEY (`mid`) REFERENCES `menu` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
   CONSTRAINT `role_menu_ibfk_2` FOREIGN KEY (`rid`) REFERENCES `role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
 )
  数据
INSERT INTO `role_menu` VALUES (1, 1, 1);
 INSERT INTO `role_menu` VALUES (2, 2, 1);
 INSERT INTO `role_menu` VALUES (3, 3, 1);
 INSERT INTO `role_menu` VALUES (4, 4, 1);
 INSERT INTO `role_menu` VALUES (5, 5, 1);
 INSERT INTO `role_menu` VALUES (6, 2, 2);
 INSERT INTO `role_menu` VALUES (7, 5, 2);
 user表  用户表
 DROP TABLE IF EXISTS `user`;
 CREATE TABLE `user`  (
   `id` int(0) NOT NULL AUTO_INCREMENT,
   `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
   `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
   `enabled` bit(1) NULL DEFAULT NULL,
   `locked` bit(1) NULL DEFAULT NULL,
   PRIMARY KEY (`id`) USING BTREE
 ) 
数据
INSERT INTO `user` VALUES (1, 'sale', '111', b'1', b'0');
 INSERT INTO `user` VALUES (2, 'admin', '111', b'1', b'0');

 user_role 用户-角色表

 DROP TABLE IF EXISTS `user_role`;
 CREATE TABLE `user_role`  (
   `id` int(0) NOT NULL AUTO_INCREMENT,
   `uid` int(0) NULL DEFAULT NULL,
   `rid` int(0) NULL DEFAULT NULL,
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `uid`(`uid`) USING BTREE,
   INDEX `rid`(`rid`) USING BTREE,
   CONSTRAINT `user_role_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
   CONSTRAINT `user_role_ibfk_2` FOREIGN KEY (`rid`) REFERENCES `role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
 ) 
 ​
 ​
 数据
 INSERT INTO `user_role` VALUES (1, 1, 2);
 INSERT INTO `user_role` VALUES (3, 2, 1);

2.建立boot项目

本次采用 父子工程方式: 其中 springboot 版本为 2.7.3 ,

父工程的pom.xml

 

     
         
             org.springframework.boot
             spring-boot-dependencies
             2.7.3
             import
             pom
         
 ​
         
         
             mysql
             mysql-connector-java
             8.0.30
             import
             pom
         
         
         
             org.projectlombok
             lombok
             1.18.24
             import
             pom
         
     
 

子工程

 
     
         org.springframework.boot
         spring-boot-starter-web
     
     
         org.springframework.boot
         spring-boot-starter-security
     
 ​
     
         com.baomidou
         mybatis-plus-boot-starter
         3.5.2
     
     
         mysql
         mysql-connector-java
     
 ​
     
         org.projectlombok
         lombok
     
 ​
     
         org.springframework.boot
         spring-boot-starter-thymeleaf
         2.7.3
     
 ​
 ​
     
     
         org.thymeleaf.extras
         thymeleaf-extras-springsecurity5
         3.0.4.RELEASE
     
 ​
 

3.创建实体层

需要创建 Menu与 User ,Role 三个实体类

 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 public class Menu {
     private int id;
     private String pattern;
     private List roles;  // 菜单对应的角色
 ​
 ​
 }

 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 public class Role {
 ​
     private Integer id;
     private String name;
     private String nameZh;
     
 }

User 需要 实现UserDetails 接口

 
package com.entity;
 ​
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetails;
 ​
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 ​
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 public class User implements UserDetails {
 ​
     private Integer id;
     private String username;
     private String password;
     private boolean enabled;
     private boolean locked;
     private Listroles;   //用户对应的角色
 ​
 ​
     // 返回当前用户的权限列表
     @Override
     public Collection getAuthorities() {
        List authorities=new ArrayList<>();
        for(Role role:roles){
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return authorities;
     }
 ​
     @Override
     public String getPassword() {
         return this.password;
     }
 ​
     @Override
     public String getUsername() {
         return this.username;
     }
     //账号是否未过期,直接返回true 表示账户未过期,也可以在数据库中添加该字段
     @Override
     public boolean isAccountNonExpired() {
         return true;
     }
     //账号是否被锁, 这里和数据库中的locked字段刚好相反,所有取反
     @Override
     public boolean isAccountNonLocked() {
         return !this.locked;
     }
     //密码是否为过期,数据库中无该字段,直接返回true
     @Override
     public boolean isCredentialsNonExpired() {
         return true;
     }
     //账户是否可用,从数据库中获取该字段
     @Override
     public boolean isEnabled() {
         return this.enabled;
     }
 }

4.增加yaml配置

数据源及mybatis-plus配置

 spring:
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://localhost:3306/security?serverTimezone=GMT%2B8
     username: 自己的用户名
     password: 自己的密码
 mybatis-plus:
   mapper-locations: classpath:mapper/*Mapper.xml
   type-aliases-package: com.entity
   configuration:
     log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

5.创建mapper层

创建 MenuMapper

 
package com.mapper;
 ​
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.entity.Menu;
 import java.util.List;
 ​
 ​
 public interface MenuMapper extends BaseMapper {
         //查询所有的菜单项(权限)
         List getAllMenus();
 ​
 }

MenuMapper.xml

 
 
 
 ​
     
         
         
         
             
             
             
         
     
 ​
     
 ​
 

UserMapper.java

 
package com.mapper;
 ​
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.entity.Role;
 import com.entity.User;
 import java.util.List;
 ​
 ​
 public interface UserMapper extends BaseMapper {
 ​
      //根据用户名 查询 用户信息
      User loadUserByUsername(String username);
 ​
      //获取当前用户的角色
      List getUserRolesById(int uid);
 ​
 }

UserMapper.xml

 
 
 
 ​
 ​
     
 ​
     
 ​
 

 

 

你可能感兴趣的:(Spring,Security,spring,数据库,java)