SpringSecurity
中,如果我们在认证或者授权的过程中出现了异常会被 ExceptionTranslationFilter
捕获到。在 ExceptionTranslationFilter
中会去判断是认证失败还是授权失败出现的异常。
如果是认证过程中出现的异常会被封装成 AuthenticationException
然后调用 AuthenticationEntryPoint
对象的方法去进行异常处理。
如果是授权过程中出现的异常会被封装成 AccessDeniedException
然后调用 AccessDeniedHandler
对象的方法去进行异常处理。
说人话就是,先实现 AuthenticationEntryPoint,再实现 AccessDeniedHandler,最后在 SecurityConfig 里面使用 http 启用它们即可
编写完这两个异常处理类后,进入 SecurityConfig,接着激活他们
// 别忘了先自动装配
@Autowired
private AuthenticationEntryPointImpl authenticationEntryPoint;
@Autowired
private AccessDeniedHandlerImpl accessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
...
// 注册两个异常捕获对象
http.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler);
}
浏览器出于安全的考虑,使用 XMLHttpRequest 对象发起 HTTP 请求时必须遵守同源策略,否则就是跨域的 HTTP 请求,默认情况下是被禁止的。
对于前后端分离项目,前端请求后端接口必定会出现跨域问题,需要对此进行特殊处理
springsecurity 的跨域问题设置极其简单,只需要两步就可以完成
新建配置类,注入配置,编辑跨域规则
代码清单:/config/CorsConfig.java
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路径
registry.addMapping("/**")
// 设置允许跨域请求的域名
.allowedOriginPatterns("*")
// 是否允许cookie
.allowCredentials(true)
// 设置允许的请求方式
.allowedMethods("GET", "POST", "DELETE", "PUT")
// 设置允许的header属性
.allowedHeaders("*")
// 跨域允许时间
.maxAge(3600);
}
}
最后一步!直接在 SecurityConfig 里面开启跨域即可
@Override
protected void configure(HttpSecurity http) throws Exception {
...
//允许跨域
http.cors();
}
还记得我们之前在 controller 中设置的 @PreAuthorize
注解吗,当时采用的是 hasAuthority
方法来执行校验流程,而实际上还有另外三种校验方法供我们选择
hasAnyAuthority
可以说是 hasAuthority 的升级版,他接受多个权限,只要用户具有其中的一个权限,那么就放行@PreAuthorize("hasAnyAuthority('admin','test','system:dept:list')")
public String hello(){
return "hello";
}
hasRole
检测用户角色是否符合对应值,特别注意,这里设置的值前面会自动拼接ROLE_
前缀@PreAuthorize("hasRole('system:dept:list')")
public String hello(){
return "hello";
}
hasAnyRole
同理,多用户判断自定义组件 SGExpressionRoot,使用注解进行注入,这里要传入一个自定义的名称
// 注入时传入自定义名称custom
@Component("custom")
public class SGExpressionRoot {
public boolean hasAuthority(String authority){
//获取当前用户的权限
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
List<String> permissions = loginUser.getPermissions();
//判断用户权限集合中是否存在authority
return permissions.contains(authority);
}
}
接着就可以在 controller 里面调用自定义的校验方式
@RequestMapping("/hello")
@PreAuthorize("@ex.hasAuthority('system:dept:list')")
public String hello(){
return "hello";
}