spring security自定义授权,权限校验总为false
@Component("rbacService")
public class RBACService {
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
Object principal = authentication.getPrincipal();
if (principal instanceof LoginUser) {//instanceof编译器会检查 obj 是否能转换成右边的class类型
LoginUser LoginUser = (LoginUser) principal;
//req.getRequestURI() 当前请求的路径
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(request.getRequestURI());
//userDetails.getAuthorities() // 用户所拥有的所有资源
Collection<? extends GrantedAuthority> authorities = LoginUser.getAuthorities();
System.out.println(simpleGrantedAuthority);
// 输出:/api/test1
System.out.println(authorities);
// 输出:[{"authority":"/api/test1"}, {"authority":"/api/test2"}, {"authority":"/api/test3"}, {"authority":"/api/test4"}]
boolean contains = authorities.contains(simpleGrantedAuthority);
System.out.println(contains);
// 输出:false(问题1:存在权限也为false?)
return contains;
}
return false;
}
}
问题2:一次请求RBACService却被调用两次,这是为何?
第二次被调用的截图:
security配置类如下:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
return http
// 跨域配置
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// 配置路径是否需要认证
// .authorizeHttpRequests()
.authorizeRequests()
// 允许匿名访问
.antMatchers("/api/auth/**").permitAll()
// 注意:.anyRequest()只能出现一次,否则报错:Caused by: java.lang.IllegalStateException: Can't configure anyRequest after itself
.anyRequest().access("@rbacService.hasPermission(request,authentication)")
.and()
//关闭csrf (注意:允许匿名访问,但不关闭csrf访问也是报403)
.cors().configurationSource(this.corsConfigurationSource())
.and()
// 禁用缓存,使用无状态session,即不使用session缓存数据
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// 添加JWT过滤器
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
/**
*跨域资源配置
*/
@Bean
public CorsConfigurationSource corsConfigurationSource(){
CorsConfiguration cors = new CorsConfiguration();
cors.addAllowedOriginPattern("*");
// TODO 正式项目为保安全须设置cors
// cors.setAllowedOriginPatterns(List.of("http://192.168.1.6:8887"));
cors.setAllowCredentials(true);
cors.addAllowedHeader("*");
cors.addAllowedMethod("*");
cors.addExposedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", cors);
return source;
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
/**
* TODO 四 4.4 基于用户名和密码或使用用户名和密码进行身份验证
* @param config
* @return
* @throws Exception
*/
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
}
当 Spring Security 中的自定义授权权限校验总为 false 时,需要确保权限字符串格式正确,权限控制器绑定正确,自定义权限校验器能够正确地进行权限校验。
可能有以下几个原因:
1. 权限字符串格式问题
首先,我们需要确保权限字符串的格式正确。在授权时,我们可以将角色和权限都表示成字符串,Spring Security 需要通过这些字符串来判断用户是否具有某些角色或权限。例如,我们可以将管理员设定为 `ROLE_ADMIN` 这样的字符串,然后将 `hasRole('ROLE_ADMIN')` 作为表达式来进行校验。
如果权限字符串的格式不正确,那么就会导致授权校验失败。请检查权限字符串的格式是否正确。
2. 权限控制器绑定问题
其次,我们需要确保自定义的权限控制器被正确地绑定到了 Spring Security 中。为了在 Spring Security 中生效,我们需要将自定义的权限控制器进行注册,例如,我们可以在 `WebSecurityConfig` 中进行注册:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomPermissionEvaluator permissionEvaluator;
@Override
public void configure(WebSecurity web) throws Exception {
// 注册自定义的权限控制器
DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
handler.setPermissionEvaluator(permissionEvaluator);
web.expressionHandler(handler);
}
// ... 其它配置代码
}
在上述代码中,我们通过 `DefaultWebSecurityExpressionHandler` 将自定义的权限控制器绑定到了 Spring Security 中。
3. 自定义权限校验器问题
最后,我们需要确保自定义的权限校验器能够正确地进行权限校验。在 Spring Security 中,我们可以通过自定义的 PermissionEvaluator 来对权限进行校验。在校验过程中,会调用 `hasPermission()` 方法,如果该方法返回 false,那么就会导致授权校验失败。
一种可能的情况是,我们在自定义的 PermissionEvaluator 中实现了 `hasPermission()` 方法,但是没有正确地将其注册到了 Spring Security 中。为了使自定义的 PermissionEvaluator 生效,我们需要在 `WebSecurityConfig` 中完成如下配置:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomPermissionEvaluator permissionEvaluator;
@Override
public void configure(WebSecurity web) throws Exception {
// 注册自定义的权限控制器
DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
handler.setPermissionEvaluator(permissionEvaluator);
web.expressionHandler(handler);
}
// 注册自定义的 PermissionEvaluator
@Bean
public DefaultMethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(permissionEvaluator);
return expressionHandler;
}
// ... 其它配置代码
}
在上述代码中,通过 `DefaultMethodSecurityExpressionHandler` 来注册自定义的 PermissionEvaluator。