Spring Security(3)——异常处理

本文详细介绍了SpringSecurity中常见的异常类型及其处理流程,包括UsernameNotFoundException、DisabledException等,并通过实例展示了如何自定义异常处理和配置Controller来捕获并显示异常信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异常处理

我们在这里只是介绍下Spring Security的简单的异常的抓取。并不做源码的分析。

一, 常见的异常
  • UsernameNotFoundException
    用户不存在,但是我程序中抛出该异常的时候,常常抓取到的是BadCredentialsException异常
    这种情况,我们可以自定义异常,继承AuthenticationException 类
  • DisabledException
    用户已经被禁用
  • BadCredentialsException
    坏的凭证
  • LockedException
    账户锁定
  • AccountExpiredException
    账户过期
  • CredentialsExpiredException
    证书过期

    上面的这些异常都是AuthenticationException的子类。
二, spring security的异常处理过程

(1)AbstractAuthenticationProcessingFilter.doFilter()

(2)AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication()

(3)SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure()

  • 这个方法中,首先会判断有没有设置的defaultFailureUrl
  • 如果没有设置,直接返回401错误,即HttpStatus.UNAUTHORIZED
  • 如果设置了首先会执行saveException方法,然后判断forwardToDestination,即是否服务器跳转,默认使用重定向。

(4)SimpleUrlAuthenticationFailureHandler.saveException()

  • 首先判断forwardToDestination
  • 如果使用服务器跳转则写入Request(转发)
  • 如果使用客户端跳转则写入Session(重定向)
  • 将对应的异常信息,写到SPRING_SECURITY_LAST_EXCEPTION ,值为 BadCredentialsException
三, 异常抓取代码

异常的抓取我们需要自己写一个Controller去接取配置的若出错重定向到的页面

  • 配置类
/**
     * 定制登陆行为
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login")
                .defaultSuccessUrl("/sayHello")
                .failureUrl("/login/error")
                .permitAll()
                .and()
                .logout().permitAll()
                // 自动登录的校验
                .and().rememberMe()
                .tokenRepository(persistentTokenRepository())
                // 声明有效时间,单位是s
                .tokenValiditySeconds(60)
                // 进行校验的service
                .userDetailsService(userDetailsService);

        // 关闭CSRF
        http.csrf().disable();
    }

里面的.
(1)failureUrl():这个表示的就是重定向,就是客户端跳转,写到session中
(2).failureForwardUrl():这个方法表示的是转发,就是服务端跳转,写到request中

  • Controller类
    @RequestMapping("/login/error")
    public void loginError(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("text/html;charset=utf-8");
        AuthenticationException exception =
                (AuthenticationException)request.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
        try {
            response.getWriter().write(exception.toString());
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

### 自定义 Spring Security 异常处理机制 为了实现更灵活的错误响应,在 Spring Security 中可以自定义异常处理逻辑。这不仅有助于提高用户体验,还能增强系统的健壮性和可维护性。 #### 创建全局异常处理器 通过创建一个实现了 `HandlerExceptionResolver` 接口或标注有 `@ControllerAdvice` 注解的类来捕获并处理未被控制器层捕捉到的安全相关异常[^1]: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(AccessDeniedException.class) public ResponseEntity<String> handleAccessDeniedException() { return new ResponseEntity<>("You do not have permission to access this resource.", HttpStatus.FORBIDDEN); } @ExceptionHandler(AuthenticationException.class) public ResponseEntity<String> handleAuthenticationException() { return new ResponseEntity<>("Invalid credentials provided.", HttpStatus.UNAUTHORIZED); } } ``` 上述代码片段展示了两个常见的安全异常——访问拒绝 (`AccessDeniedException`) 和认证失败 (`AuthenticationException`) 的处理方式。每当这些特定类型的异常抛出时,就会触发相应的方法执行,并返回带有适当 HTTP 状态码的消息给客户端。 #### 配置自定义的身份验证入口点 对于想要改变默认行为的情况,比如当用户尝试登录但未能成功时所看到的信息页面或者重定向路径,则可以通过设置自定义的身份验证入口来进行调整: ```java @Override protected void configure(HttpSecurity http) throws Exception { http.exceptionHandling() .authenticationEntryPoint(new CustomAuthenticationEntryPoint()); } // 定义自己的 AuthenticationEntryPoint 实现 public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { // 设置响应头和状态码等操作... response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); } } ``` 这里展示了一个简单的例子,其中 `CustomAuthenticationEntryPoint` 类负责在发生未经授权请求的情况下向客户端发送 401 错误以及一条消息说明原因。 #### 使用过滤器链中的异常转换器 有时可能希望将某些内部发生的低级异常映射成更高层次的应用程序级别的异常以便更好地控制其传播范围。这时可以在配置文件里指定一个 `ExceptionTranslationFilter` 来完成这项工作: ```java @Bean public ExceptionTranslationFilter exceptionTranslationFilter() { ExceptionTranslationFilter filter = new ExceptionTranslationFilter(); // 可以为不同的原始异常类型分配对应的高级别异常对象 Map<Class<? extends Throwable>, AccessDeniedException> mapping = Collections.singletonMap( SomeInternalException.class, (AccessDeniedException)new AccessDeniedException("Mapped from internal error.") ); filter.setExceptionMapping(mapping); return filter; } ``` 这段代码允许开发者根据实际需求定义从一种异常到另一种之间的映射关系,从而简化了跨组件间的异常管理流程
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值