Spring Security权限管理实例分析
导读:本文共15963字符,通常情况下阅读需要53分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要:接下来,请跟着小编一起来学习吧!1 Spring Security配置用户名和密码方式一:在application.properties文件中配置#配置security用户名密码spring.security.user.password=LIFEILINspring.security.user.name=LIFEILINspring.security.user.roles=admin方式二:... ...
目录
(为您整理了一些要点),点击可以直达。接下来,请跟着小编一起来学习吧!
1 Spring Security配置用户名和密码
方式一:在application.properties文件中配置
#配置security用户名密码
spring.security.user.password=LIFEILIN
spring.security.user.name=LIFEILIN
spring.security.user.roles=admin
方式二:代码配置
@Configuration
publicclasssecurityConfigextendsWebSecurityConfigurerAdapter{//暂且密码不加密
@Bean
PasswordEncoderpasswordEncoder(){
returnNoOpPasswordEncoder.getInstance();
}@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
auth.inMemoryAuthentication()
.withUser("LIFEILIN").password("LIFEILIN").roles("admin")//第一个
.and()
.withUser("123").password("123").roles("user");//第二个
}
}
2 HttpSecurity的配置
//配置HttpSecurity拦截规则
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http.authorizeRequests()//开启配置
.antMatchers("/admin/").hasRole("admin")
.antMatchers("/user/").hasAnyRole("admin","user")
.anyRequest().authenticated()//其他请求登录后即可访问
.and()
.formLogin()
.loginProcessingUrl("/doLogin")
.permitAll()//跟登录相关接口直接访问
.and()
.csrf().disable();
}
3 登录/注销表单详细配置
//配置HttpSecurity拦截规则
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http.authorizeRequests()//开启配置
.antMatchers("/admin/").hasRole("admin")
.antMatchers("/user/").hasAnyRole("admin","user")
.anyRequest().authenticated()//其他请求登录后即可访问
.and()
.formLogin()
.loginProcessingUrl("/doLogin")
//.loginPage("login")//登录页面
//自定义用户名密码
.usernameParameter("uname")
.passwordParameter("passwd")
//登录成功的处理器(前后端分离)
.successHandler(newAuthenticationSuccessHandler(){
@Override
publicvoidonAuthenticationSuccess(HttpServletRequestreq,HttpServletResponseresp,Authenticationauthentication)throwsIOException,ServletException{//authentication为登录成功对象
//登录成功,返回json
resp.setContentType("application/json;charset=utf-8");
PrintWriterout=resp.getWriter();
Map<String,Object>map=newHashMap<>();
map.put("status",200);
map.put("msg",authentication.getPrincipal());//登录成功对象
out.write(newObjectMapper().writeValueAsString(map));//将map转为json写出去
out.flush();
out.close();
}
})
//登录失败的处理器(前后端分离)
.failureHandler(newAuthenticationFailureHandler(){
@Override
publicvoidonAuthenticationFailure(HttpServletRequestreq,HttpServletResponseresp,AuthenticationExceptione)throwsIOException,ServletException{
resp.setContentType("application/json;charset=utf-8");
PrintWriterout=resp.getWriter();
Map<String,Object>map=newHashMap<>();
map.put("status",401);
if(einstanceofLockedException){//账号锁定
map.put("msg","账号被锁定,登录失败");
}elseif(einstanceofBadCredentialsException){
map.put("msg","用户名和密码输入错误,登录失败");
}elseif(einstanceofDisabledException){
map.put("msg","账号被禁用,登录失败");
}elseif(einstanceofAccountExpiredException){
map.put("msg","账户过期,登录失败");
}elseif(einstanceofCredentialsExpiredException){
map.put("msg","密码过期,登录失败");
}else{
map.put("msg","登录失败");
}
out.write(newObjectMapper().writeValueAsString(map));//将map转为json写出去
out.flush();
out.close();
}
})
.permitAll()//跟登录相关接口直接访问
.and()
//注销登录
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(newLogoutSuccessHandler(){
@Override
publicvoidonLogoutSuccess(HttpServletRequestreq,HttpServletResponseresp,Authenticationauthentication)throwsIOException,ServletException{
resp.setContentType("application/json;charset=utf-8");
PrintWriterout=resp.getWriter();
Map<String,Object>map=newHashMap<>();
map.put("status",200);
map.put("msg","注销登录成功");//注销登录成功
out.write(newObjectMapper().writeValueAsString(map));//将map转为json写出去
out.flush();
out.close();
}
})
.and()
.csrf().disable();
}
4 多个HttpSecurity的配置
配置类不需要继承WebSecurityConfigurerAdapter方法,直接注入:configure方法
@Configuration
publicclassMultiHttpSecurityConfig{
//暂且密码不加密
@Bean
PasswordEncoderpasswordEncoder(){
returnNoOpPasswordEncoder.getInstance();
}//配置用户名和密码
@Autowired
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
auth.inMemoryAuthentication()
.withUser("LIFEILIN").password("LIFEILIN").roles("admin")//第一个
.and()
.withUser("123").password("123").roles("user");//第二个
}@Configuration
@Order(1)
publicstaticclassAdminSecurityConfigextendsWebSecurityConfigurerAdapter{
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http.antMatcher("/admin/**").authorizeRequests().anyRequest().hasRole("admin");//admin角色访问
}
}@Configuration
publicstaticclassOtherSecurityConfigextendsWebSecurityConfigurerAdapter{
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/doLogin")
.permitAll()
.and()
.csrf().disable();
}
}
}
5 密码加密
相同的明文可加密成不同的密文,不用维护原字段。
@Test
voidcontextLoads(){
for(inti=0;i<10;i++){
BCryptPasswordEncoderencoder=newBCryptPasswordEncoder();
System.out.println(encoder.encode("123"));}
}
明文【123】加密后:
$2a 10 10 10SS.YDon5lzqkIFdW8DQYzOTJBvQwkdXHWcHlIfF1fa/wPjJtru5aO
$2a 10 10 10vJsPq4GBtHKmmBQaKTriTO90sFurCEDavZANqCoqGu4gAzXxGLbTC
$2a 10 10 10gZ4H3/tBRpz2lPX0XUI1ber2qsNsKuk38j0iSsATeVOrrWFJIEr1G
$2a 10 10 10h7RiyAXP8JzWGsmAXGZy/uO6ASraQPNryVPl.11vMyUjhSCxS.Sde
$2a 10 10 10BCm3vuueGWdvjG3ciCUZB.6V9y6jMELHqB9iv2DwRJyOkR5jd…4S
$2a 10 10 10rO2894WmxRMtjHVzoYivyuzvje8BrAUjm8YLj3K.i4sQDvpWBtuuy
$2a 10 10 10jTosyN75hwKB3OSQCYY9YOIj6TYZG1FdJXfYCalTUuXpPiI5tv/P.
$2a 10 10 10p95j18H3yRABEScCE/2MqOqYt1ZqArdYhC87BVGEmQvn6znSqKw5G
$2a 10 10 10/y8FGBlvod1Dnq29c2scs.eGnYfvezZIZwfDHoXFfgIVA7H0T17pO
$2a 10 10 10k8IKAv4dBXhooEU8Qgo6E.PcrQ/ICymqNGLyE8Jfo4V1nk61GMeuy
6 方法安全
在配置类中添加注解:@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
接口都能访问,但进了接口不一定能访问到接口里面的方法!!
【Controller层:】
@Autowired
MethodServicemethodService;@GetMapping("/hello1")
publicStringhello1(){
returnmethodService.admin();
}
@GetMapping("/hello2")
publicStringhello2(){
returnmethodService.user();
}
@GetMapping("/hello3")
publicStringhello3(){
returnmethodService.hello();
}
【Service层:】
@Service
publicclassMethodService{
@PreAuthorize("hasRole('admin')")
publicStringadmin(){//需要admin角色才能访问
return"helloadmin";
}@Secured("ROLE_user")
publicStringuser(){//需要user角色才能访问
return"hellouser";
}@PreAuthorize("hasAnyRole('admin','user')")//admin,user两种权限
publicStringhello(){
return"hellohello";
}
}
7 基于数据库的认证
1、数据库中创建三张表user、role、user_role
2、设置配置文件
#应用名称
spring.application.name=SpringBoot_11_security应用服务WEB访问端口
server.port=8080
下面这些内容是为了让MyBatis映射
指定Mybatis的Mapper文件
mybatis.mapper-locations=classpath:mappers/*xml
指定Mybatis的实体目录
mybatis.type-aliases-package=com.example.mybatis.entity
数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
数据源名称
spring.datasource.name=defaultDataSource
数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/【数据库名称】?serverTimezone=UTC
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=【数据库密码】
3、创建实体User、Role
packagecom.example.bean;importorg.springframework.security.core.GrantedAuthority;
importorg.springframework.security.core.authority.SimpleGrantedAuthority;
importorg.springframework.security.core.userdetails.UserDetails;importjava.util.ArrayList;
importjava.util.Collection;
importjava.util.List;/*
@author李飞林
@ClassNameUser
@mail1961785612@qq.com
@DescriptionTODO
@date2022/8/421:46
*/
publicclassUserimplementsUserDetails{
privateIntegerid;
privateStringusername;
privateStringpassword;
privateBooleanenabled;
privateBooleanlocked;
privateList<Role>roles;publicList<Role>getRoles(){
returnroles;
}publicvoidsetRoles(List<Role>roles){
this.roles=roles;
}publicvoidsetId(Integerid){
this.id=id;
}publicvoidsetUsername(Stringusername){
this.username=username;
}publicvoidsetPassword(Stringpassword){
this.password=password;
}publicvoidsetEnabled(Booleanenabled){
this.enabled=enabled;
}publicvoidsetLocked(Booleanlocked){
this.locked=locked;
}publicIntegergetId(){
returnid;
}@Override
publicStringgetUsername(){
returnusername;
}@Override
publicbooleanisAccountNonExpired(){//账号是否未过期
returntrue;
}@Override
publicbooleanisAccountNonLocked(){//账号是否未锁定
return!locked;
}@Override
publicbooleanisCredentialsNonExpired(){
returntrue;
}@Override
publicbooleanisEnabled(){//是否可用
returnenabled;
}@Override
publicCollection<?extendsGrantedAuthority>getAuthorities(){
List<SimpleGrantedAuthority>authorities=newArrayList<>();
for(Rolerole:roles){
authorities.add(newSimpleGrantedAuthority("ROLE_"+role.getName()));//角色认证以ROLE_开始
}
returnauthorities;//返回用户所有角色
}@Override
publicStringgetPassword(){
returnpassword;
}
}
packagecom.example.bean;/*
@author李飞林
@ClassNameRole
@mail1961785612@qq.com
@DescriptionTODO
@date2022/8/421:49
*/
publicclassRole{
privateIntegerid;
privateStringname;
privateStringnameZh;publicIntegergetId(){
returnid;
}publicvoidsetId(Integerid){
this.id=id;
}publicStringgetName(){
returnname;
}publicvoidsetName(Stringname){
this.name=name;
}publicStringgetNameZh(){
returnnameZh;
}publicvoidsetNameZh(StringnameZh){
this.nameZh=nameZh;
}
}
4、编写mapper层
UserMapper接口:
packagecom.example.mapper;importcom.example.bean.Role;
importcom.example.bean.User;
importorg.apache.ibatis.annotations.Mapper;importjava.util.List;
/*
@author李飞林
@ClassNameUserMapper
@mail1961785612@qq.com
@DescriptionTODO
@date2022/8/422:01
*/
@Mapper
publicinterfaceUserMapper{
UserloadUserByUsername(Stringusername);List<Role>getUserRolesById(Integerid);
}
UserMapper.xml:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mappernamespace="com.example.mapper.UserMapper">
<selectid="loadUserByUsername"resultType="com.example.bean.User">
select
fromuser
whereusername=#{username};
</select>
<selectid="getUserRolesById"resultType="com.example.bean.Role">
select
fromrole
whereidin(selectridfromuser_rolewhereuid=#{id})
</select>
</mapper>
5、编写service层:
packagecom.example.service;importcom.example.bean.User;
importcom.example.mapper.UserMapper;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.security.core.userdetails.UserDetails;
importorg.springframework.security.core.userdetails.UserDetailsService;
importorg.springframework.security.core.userdetails.UsernameNotFoundException;
importorg.springframework.stereotype.Service;/*
@author李飞林
@ClassNameUserService
@mail1961785612@qq.com
@DescriptionTODO
@date2022/8/422:01
*/
@Service
publicclassUserServiceimplementsUserDetailsService{
@Autowired
UserMapperuserMapper;@Override
publicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{
Useruser=userMapper.loadUserByUsername(username);
if(user==null){
thrownewUsernameNotFoundException("用户不存在");
}
user.setRoles(userMapper.getUserRolesById(user.getId()));
returnuser;
}
}
6、security安全配置:
packagecom.example.config;importcom.example.service.UserService;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
importorg.springframework.security.config.annotation.web.builders.HttpSecurity;
importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
importorg.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
importorg.springframework.security.crypto.password.PasswordEncoder;/*
@author李飞林
@ClassNameSecurityConfig
@mail1961785612@qq.com
@DescriptionTODO
@date2022/8/422:35
*/
@Configuration
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
@Autowired
UserServiceuserService;@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
auth.userDetailsService(userService);
}@Bean
PasswordEncoderpasswordEncoder(){
returnnewBCryptPasswordEncoder();
}@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http.authorizeRequests()
.antMatchers("/dba/").hasRole("dba")
.antMatchers("/admin/").hasRole("admin")
.antMatchers("/user/**").hasRole("user")
.anyRequest().authenticated()//其他可访问
.and()
.formLogin()
.permitAll()
.and()
.csrf().disable();
}
}
7、controller层接口调试:
packagecom.example.controller;importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RestController;/*
@author李飞林
@ClassNameHelloController
@mail1961785612@qq.com
@DescriptionTODO
@date2022/8/422:40
*/
@RestController
publicclassHelloController{
@GetMapping("/hello")
publicStringhello(){
return"hellosecurity";
}@GetMapping("/dba/hello")
publicStringdba(){
return"hellodba";
}@GetMapping("/admin/hello")
publicStringadmin(){
return"helloadmin";
}@GetMapping("/user/hello")
publicStringuser(){
return"hellouser";
}
}
8 角色继承(在securityConfig中加入代码段)
//角色继承
@Bean
RoleHierarchyroleHierarchy(){
RoleHierarchyImplroleHierarchy=newRoleHierarchyImpl();
Stringhierarchy="ROLE_dba>ROLE_admin>ROLE_user";//dba>admin>user
roleHierarchy.setHierarchy(hierarchy);
returnroleHierarchy;
}
9 动态配置权限
数据库中的表结构如下:
其中菜单表中已经配置好对应的路径,后面需要从数据库中加载:
一、查询user用户所具有的角色
1、编写实体类User、Role、Menu:
User实现UserDetails接口,实现如下方法:
@Override
publicCollection<?extendsGrantedAuthority>getAuthorities(){
List<SimpleGrantedAuthority>authorities=newArrayList<>();
for(Rolerole:
roles){
authorities.add(newSimpleGrantedAuthority(role.getName()));
}
returnauthorities;
}
2、编写UserService:继承UserDetailsService接口,实现loadUserByUsername方法
@Service
publicclassUserServiceImplextendsServiceImpl<UserMapper,User>implementsUserService,UserDetailsService{
@Autowired
UserMapperuserMapper;@Override
publicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{
Useruser=userMapper.loadUserByUsername(username); //根据登录字符串获获取用户名
if(user==null){
thrownewUsernameNotFoundException("用户不存在");
}else{
user.setRoles(userMapper.getRolesById(user.getId())); //根据用户名的ID查询所具有的角色
}
returnuser;
}
}
3、编写UserMapper接口:
@Mapper
publicinterfaceUserMapperextendsBaseMapper<User>{UserloadUserByUsername(Stringusername);
List<Role>getRolesById(Integerid);
}
4、编写UserMapper.xml:
<selectid="loadUserByUsername"resultType="com.lifeilin.pojo.User">
select*
fromuser
whereusername=#{username}
</select><selectid="getRolesById"resultType="com.lifeilin.pojo.Role">
select*
fromrole
whereidin(selectridfromuser_rolewhereuid=#{id});
</select>
至此,已经从数据库中获取到登录用户user所具备的角色
二、配置SecurityConfig
1、在SecurityConfig类中配置登录权限
@Configuration
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{
@Autowired
UserServiceImpluserService;@Bean
PasswordEncoderpasswordEncoder(){
returnnewBCryptPasswordEncoder();
}//配置登录
@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
auth.userDetailsService(userService);
}
}
2、配置角色(从数据库中动态加载) 1 在config包中创建MyFilter.java过滤器
在config包中创建MyFilter.java过滤器,实现FilterInvocationSecurityMetadataSource接口,其主要作用是分析请求地址,请求地址必然是menu表中给出的标准地址(如果不是则进行其他操作),根据请求地址分析出需要哪些角色
注意:这里需要提前从数据库查询出所有菜单以及对应的角色。
补充:查询菜单及对应角色(使用Spring Cache作缓存)
1、导入缓存相关依赖
<!--redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--cache依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2、需要简单配置一下Redis,Redis的基本信息,另外,这里要用到Cache,因此还需要稍微配置一下Cache,如下:
##配置redis基本属性
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0
spring.redis.password=配置cache名称
spring.cache.cache-names=c1
另外,还需要在配置类上添加如下代码,表示开启缓存:
3、Service层缓存的使用
(1)在MenuServiceImpl类上使用@CacheConfig(cacheNames = “c1”)br/>这个注解在类上使用,用来描述该类中所有方法使用的缓存名称,当然也可以不使用该注解,直接在具体的缓存注解上配置名称。<br/>(2)在MenuServiceImpl类下getAllMenus()方法使用@Cacheable<br/这个注解一般加在查询方法上,表示将一个方法的返回值缓存起来,默认情况下,缓存的key就是方法的参数,缓存的value就是方法的返回值。
@Service
@CacheConfig(cacheNames="c1")
publicclassMenuServiceImplextendsServiceImpl<MenuMapper,Menu>implementsMenuService{
@Autowired
MenuMappermenuMapper;//可以加缓存
@Cacheable
publicList<Menu>getAllMenus(){
returnmenuMapper.getAllMenus();
}
}
@Mapper
publicinterfaceMenuMapperextendsBaseMapper<Menu>{List<Menu>getAllMenus();
}
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mappernamespace="com.lifeilin.mapper.MenuMapper">
<!--查询所有menu-->
<!--resultMap:填入配置的resultMap标签的id值-->
<selectid="getAllMenus"resultMap="BaseResultMap">
SELECTm.id,
m.pattern,
r.idASrid,
r.NAMEASrname,
r.nameZhASrnameZh
FROMmenuASm
LEFTJOINmenu_roleASmrONm.id=mr.mid
LEFTJOINroleASrONmr.rid=r.id
</select>
<!--resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo-->
<resultMapid="BaseResultMap"type="com.lifeilin.pojo.Menu">
<!--定义主键,非常重要。如果是多个字段,则定义多个id-->
<!--property:主键在pojo中的属性名-->
<!--column:主键在数据库中的列名-->
<idproperty="id"column="id"></id>
<!--定义普通属性-->
<resultproperty="pattern"column="pattern"></result>
<!--collection中property的roles对应的是Role实体中的属性-->
<collectionproperty="roles"ofType="com.lifeilin.pojo.Role">
<idcolumn="rid"property="id"/>
<resultcolumn="rname"property="name"/>
<resultcolumn="rnameZh"property="nameZh"/>
</collection>
</resultMap>
</mapper>
@Component
publicclassMyFilterimplementsFilterInvocationSecurityMetadataSource{
//路径匹配符
AntPathMatcherpathMatcher=newAntPathMatcher();@Autowired
MenuServiceImplmenuService;@Override
publicCollection<ConfigAttribute>getAttributes(Objectobject)throwsIllegalArgumentException{
StringrequestUrl=((FilterInvocation)object).getRequestUrl();//获取请求的地址
List<Menu>allMenus=menuService.getAllMenus();//查询所有菜单
for(Menumenu:allMenus){
if(pathMatcher.match(menu.getPattern(),requestUrl)){//请求地址与菜单地址匹配上
List<Role>roles=menu.getRoles();//获取匹配成功的地址的角色
String[]rolesStr=newString[roles.size()];
for(inti=0;i<roles.size();i++){
rolesStr[i]=roles.get(i).getName();
}
returnSecurityConfig.createList(rolesStr);
}
}
returnSecurityConfig.createList("ROLE_login");//没有匹配上,标记符,额外处理
}@Override
publicCollection<ConfigAttribute>getAllConfigAttributes(){
returnnull;
}@Override
publicbooleansupports(Class<?>clazz){
returntrue;
}
}
2、在config包中创建MyAccessDecisionManager类
在config包中创建MyAccessDecisionManager类,目的是通过上一步获取了请求路径需要哪些角色看看数据库中是否具有该角色。
@Component
publicclassMyAccessDecisionManagerimplementsAccessDecisionManager{
@Override
publicvoiddecide(Authenticationauthentication,Objectobject,Collection<ConfigAttribute>configAttributes)throwsAccessDeniedException,InsufficientAuthenticationException{//authentication知道有哪些角色,configAttributes知道需要哪些角色
//1、遍历需要的角色
for(ConfigAttributeattribute:configAttributes){
if("ROLE_login".equals(attribute.getAttribute())){//请求地址都没匹配上,说明是登陆后就可访问的请求地址
if(authenticationinstanceofAnonymousAuthenticationToken){//匿名用户(没登陆)
thrownewAccessDeniedException("非法请求");
}else{
return;
}
}
//2、获取所具备的角色
Collection<?extendsGrantedAuthority>authorities=authentication.getAuthorities();
for(GrantedAuthorityauthority:authorities){
if(authority.getAuthority().equals(attribute.getAttribute())){//如果具备所需要的角色
return;
}
}
}
thrownewAccessDeniedException("非法请求");
}@Override
publicbooleansupports(ConfigAttributeattribute){
returntrue;
}@Override
publicbooleansupports(Class<?>clazz){
returntrue;
}
}
3、在SecurityConfig引入myAccessDecisionManager + myFilter
@Override若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http.authorizeRequests()
.withObjectPostProcessor(newObjectPostProcessor<FilterSecurityInterceptor>(){
@Override
public<OextendsFilterSecurityInterceptor>OpostProcess(Oobject){
object.setAccessDecisionManager(myAccessDecisionManager);//
object.setSecurityMetadataSource(myFilter);//
returnobject;
}
})
.and()
.formLogin()
.permitAll()
.and()
.csrf().disable();
}
Spring Security权限管理实例分析的详细内容,希望对您有所帮助,信息来源于网络。