Spring Boot下Spring Security权限认证@PreAuthorize注解失效
根据我的经历,一共有三种情况。如果谁还遇到其他情况可以提出来。
第一种情况。
就是网上大量出现的。没有添加 @EnableGlobalMethodSecurity 注解。
还有 @EnableGlobalMethodSecurity 注解只能添加在继承了WebSecurityConfigurerAdapter
的类上面。
package com.jiang.login.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* SecurityConfig 登录认证的配置
*
* @创建人 江枫沐雪
* @创建时间 2021/7/16 9:09
*/
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("myUserDetailsService")
private UserDetailsService userDetailsService;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
//查询用户信息
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//用户详情信息
auth.userDetailsService(userDetailsService)
//密码加密方式
.passwordEncoder(bCryptPasswordEncoder);
}
//安全拦截机制
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
//配置跨域请求 并且 关闭打开的csrf保护
.cors().and()
.csrf().disable()
// 认证配置
.authorizeRequests()
// 登录验证等放行
.antMatchers("/auth/**","/app/**").permitAll()
// .antMatchers("/per/get").hasAuthority("GET_PER")
// .antMatchers("/per/getPer").hasAuthority("GET_PER")
// .antMatchers("/per/getPer").access("hasRole('ROlE_GET')")
// 剩下的接口都需要登陆后访问
.anyRequest().authenticated()
.and()
//表单登录
.formLogin()
// 用户未登录的的时候跳转的这个路径
.loginPage("/home")
// 用户登录时,用户名、密码提交的目的路径
.loginProcessingUrl("/login")
// 用户成功登录以后
.successForwardUrl("/success")
.and()
.logout()
.logoutUrl("/logout");
// .logoutSuccessUrl("/log")
}
}
第二种情况
就是,你的 @PreAuthorize 注解使用的角色授权,不是资源(权限)授权。
@PreAuthorize(“hasRole(‘USER’)”)
因为你使用的是角色授权,所以Spring Security会自动在你设置的参数前加上一个ROLE_,那么你在添加角色权限的时候传递的差数是ROLE_USER。
例如:
UserDetails userDetails = User.withUsername(user.getUsername())
.password(user.getPassword()).roles("ROLE_USER");
第三种情况
这是我遇见非常诡异的情况。
@PreAuthorize(“hasAuthority(‘GET_PER’)”) 不能生效。
首先我创建了一个LoginController的controller文件,然后在创建了一个测试接口
/**
* Lonig
*
* @创建人 江枫沐雪
* @创建时间 2021/7/26 14:37
*/
@RestController
public class LoginController {
@PostMapping("/per/get")
@PreAuthorize("hasAuthority('GET_PER')")
private String getPerm(){
return "拥有权限!";
}
}
但这个测试接口无论如何都无法拦截,但我使用web方法授权就可以。
我调了几个小时,依然没有解决。
但神奇的事情来了。
我又创建了一个controller类RoleController 在他下面重新写了一个普通的查询方法,竟然可以拦截。
于是,我就又在RoleController重新写了一个普通的测试接口,结果成功拦击。
o((⊙﹏⊙))o
当时,我已经懵了!!!
最后,我想是不是我LoginController有问题,我就把LoginController中的方法粘贴复制了过来,发现不能拦截!!!
@RestController
@RequestMapping("role")
public class RoleController {
@Autowired
private RoleService roleService;
//
@GetMapping("get")
@PreAuthorize("hasAuthority('GET_ROLE')")
public ApiResponse getRole(){
return ApiResponseWithData.ofSuccess(roleService.getRole());
}
//
@GetMapping("permin")
@PreAuthorize("hasAuthority('GET_PERMIN')")
public string getPerMin(){
return "真的好神奇!";
}
//从LoginController中粘贴复制过了,但依然不能拦截
@PostMapping("/per")
@PreAuthorize("hasAuthority('GET_PER')")
private string getPer(){
return "拥有权限!";
}
}
最后,我放弃寻找原因,因为其他的都可以权限控制。