当前位置: 代码迷 >> 综合 >> 三、SpringSecurity+auth2.0系列(动态权限控制,基于数据库进行设计)
  详细解决方案

三、SpringSecurity+auth2.0系列(动态权限控制,基于数据库进行设计)

热度:42   发布时间:2023-12-11 16:10:52.0

!!!!注意 ,本项目是在上一个项目的基础上循序渐进的,请移步本专栏上一个项目

Rbac权限表设计
sql表地址在这里,点击不需要积分即刻下载

RBAC(基于角色的权限控制)模型的核心是在用户和权限之间引入了角色的概念。取消了用户和权限的直接关联,改为通过用户关联角色、角色关联权限的方法来间接地赋予用户权限(如下图),从而达到用户和权限解耦的目的。
在这里插入图片描述
Maven依赖

        <!-- springboot 整合mybatis框架 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><!-- alibaba的druid数据库连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.9</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope></dependency>

配置文件

  datasource:url: jdbc:mysql://127.0.0.1:3306/orange_rbac?serverTimezone=Asia/Shanghai&allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8username: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driver

Mapper接口
导入Mapper接口
新建mapper包
新建接口与数据库交互
完整代码如下

权限mapper

package com.thunisoft.spring_security.mapper;import com.thunisoft.spring_security.model.PermissionEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;import java.util.List;@Mapper
public interface PermissionMapper {@Select(" SELECT * from sys_permission ")List<PermissionEntity> findAllPermission();
}

用户mapper

package com.thunisoft.spring_security.mapper;import com.thunisoft.spring_security.model.PermissionEntity;
import com.thunisoft.spring_security.model.UserEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper
public interface UserMapper {/*** 根据用户名查询用户* @param userName* @return*/@Select(" SELECT * from sys_user where username = #{userName}")UserEntity findByUsername(String userName);/*** 查询用户的权限根据用户查询权限** @param* @return*/@Select(" select permission.* from sys_user user" + " inner join sys_user_role user_role"+ " on user.id = user_role.user_id inner join "+ "sys_role_permission role_permission on user_role.role_id = role_permission.role_id "+ " inner join sys_permission permission on role_permission.perm_id = permission.id where user.username = #{userName};")List<PermissionEntity> findPermissionByUsername(String userName);
}

动态根据账户名称查询权限
使用UserDetailsService实现动态查询数据库验证账号
新建service包,在下面新建类
完整代码如下

package com.thunisoft.spring_security.service;import com.thunisoft.spring_security.mapper.UserMapper;
import com.thunisoft.spring_security.model.PermissionEntity;
import com.thunisoft.spring_security.model.UserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.List;@Component
public class MemberDetailsService implements UserDetailsService {@Autowiredprivate UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {//查询用户UserEntity userEntity = userMapper.findByUsername(s);if (userEntity==null){return null;}//查询用户权限List<PermissionEntity> permissionEntityList =  userMapper.findPermissionByUsername(s);ArrayList<GrantedAuthority> grantedAuthorities = new ArrayList<>();permissionEntityList.forEach((a)->{grantedAuthorities.add(new SimpleGrantedAuthority(a.getPermTag()));});// 设置权限userEntity.setAuthorities(grantedAuthorities);return userEntity;}
}

WebSecurity相关配置
完整配置如下

package com.thunisoft.spring_security.config;import com.thunisoft.spring_security.mapper.PermissionMapper;
import com.thunisoft.spring_security.model.PermissionEntity;
import com.thunisoft.spring_security.service.MemberDetailsService;
import com.thunisoft.spring_security.utils.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;import java.util.List;@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MemberDetailsService memberDetailsService;@Autowiredprivate PermissionMapper permissionMapper;@Overrideprotected void configure(HttpSecurity http) throws Exception {/*** 新增 HttpSecurity基础配置配置*/// http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();/*** 新增HttpSecurity formLogin模式*///http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().formLogin();
/*http.authorizeRequests().antMatchers("/addMember").hasAnyAuthority("addMember").antMatchers("/delMember").hasAnyAuthority("delMember").antMatchers("/showMember").hasAnyAuthority("showMember").antMatchers("/editMember").hasAnyAuthority("editMember").// antMatchers("/**").fullyAuthenticated().and().formLogin()antMatchers("/login").permitAll().antMatchers("/**").fullyAuthenticated().and().formLogin().loginPage("/login").and().csrf().disable();
*/List<PermissionEntity> allPermission = permissionMapper.findAllPermission();ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequests = http.authorizeRequests();allPermission.forEach((a)->{//地址绑定权限authorizeRequests.antMatchers(a.getUrl()).hasAnyAuthority(a.getPermTag());});authorizeRequests.antMatchers("/login").permitAll()// 设置自定义登录页面.antMatchers("/**").fullyAuthenticated().and().formLogin().loginPage("/login").and().csrf().disable();}/** 新增授权账户* */@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {//新增一个用户为orange,密码为chengyunpeng的用户可以访问是所有权限/*      auth.inMemoryAuthentication().withUser("admin").password("admin").authorities("addMember","delMember","editMember","showMember");auth.inMemoryAuthentication().withUser("orange").password("orange").authorities("showMember");*/auth.userDetailsService(memberDetailsService).passwordEncoder(new PasswordEncoder() {@Overridepublic String encode(CharSequence charSequence) {return MD5Util.encode((String)charSequence);}@Overridepublic boolean matches(CharSequence charSequence, String s) {String rawPass = MD5Util.encode((String) charSequence);boolean result = rawPass.equals(s);return result;}});}/*** 密码不做任何处理* @return*/
/*    @Beanpublic static NoOpPasswordEncoder passwordEncoder(){return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();}*/}

MD5工具类如下

package com.thunisoft.spring_security.utils;import java.security.MessageDigest;public class MD5Util {private static final String SALT = "mayikt";public static String encode(String password) {password = password + SALT;MessageDigest md5 = null;try {md5 = MessageDigest.getInstance("MD5");} catch (Exception e) {throw new RuntimeException(e);}char[] charArray = password.toCharArray();byte[] byteArray = new byte[charArray.length];for (int i = 0; i < charArray.length; i++)byteArray[i] = (byte) charArray[i];byte[] md5Bytes = md5.digest(byteArray);StringBuffer hexValue = new StringBuffer();for (int i = 0; i < md5Bytes.length; i++) {int val = ((int) md5Bytes[i]) & 0xff;if (val < 16) {hexValue.append("0");}hexValue.append(Integer.toHexString(val));}return hexValue.toString();}public static void main(String[] args) {System.out.println(MD5Util.encode("orange"));}
}

主要是websecrity的设置
运行项目进行测试
不懂的可以骚扰我

  相关解决方案