【SpringSecurity】三更草堂项目案例分析4 - 失败处理与CORS跨域

失败处理

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);
}

跨域 CROS

浏览器出于安全的考虑,使用 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 方法来执行校验流程,而实际上还有另外三种校验方法供我们选择

  1. hasAnyAuthority 可以说是 hasAuthority 的升级版,他接受多个权限,只要用户具有其中的一个权限,那么就放行
@PreAuthorize("hasAnyAuthority('admin','test','system:dept:list')")
public String hello(){
    
    
    return "hello";
}
  1. hasRole 检测用户角色是否符合对应值,特别注意,这里设置的值前面会自动拼接ROLE_前缀
@PreAuthorize("hasRole('system:dept:list')")
public String hello(){
    
    
    return "hello";
}
  1. 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";
}

猜你喜欢

转载自blog.csdn.net/delete_you/article/details/132941457