SpringBoot集成SpringSecurity(3)-----异常处理

转载:

作者:Jitwxs
来源:CSDN
原文:https://blog.csdn.net/yuanlaijike/article/details/80250389
版权声明:本文为博主原创文章,转载请附上博文链接!

概述

不知道你有没有注意到,当我们登陆失败时候,Spring security 帮我们跳转到了 /login?error Url,奇怪的是不管是控制台还是网页上都没有打印错误信息。
SpringBoot集成SpringSecurity(3)-----异常处理_第1张图片
这个因为首先 /login?error 是SrpingSecurity 默认的失败Url,其次如果你不手动处理这个异常,那么这个异常是不会被处理的

一、常见异常

  • UsernameNotFountException(用户不存在)
  • DisabledException (用户已经被禁用)
  • BadCredentialsException (坏的凭据)
  • LockedException (账户锁定)
  • AccountExpiredException (账户过期)
  • CredentialsExpiredException (证书过期)

以上列出的这些异常都是 AuthenticationException 的子类,然后我们来看看SpringSecurity如何处理AuthenticationException异常的
(1)在 doFilter() 中, 捕捉了 AuthenticationException 异常,并交给了 unsuccessfulAuthentication() 处理
SpringBoot集成SpringSecurity(3)-----异常处理_第2张图片
(2)在 unsuccessfulAuthentication() 中,转交给了SimpleUrlAuthenticationFailureHander 类的 onAuthenticationFailure() 处理
SpringBoot集成SpringSecurity(3)-----异常处理_第3张图片

  • 如果没有设置,直接返回 401 错误,即 HttpStatus.UnAUTHORIZED的值
  • 如果设置了 首先执行 saveException() 方法,然后判断forwardTodestination,是否是服务器跳转, 默认使用重定向即客户端跳转

SpringBoot集成SpringSecurity(3)-----异常处理_第4张图片
SpringBoot集成SpringSecurity(3)-----异常处理_第5张图片
(4)在 saveException() 方法中,首先判断forwardToDestination ,如果使用服务器跳转则写入Request,客户端跳转则写入Session,写入名为 SPRING_SECURITY_LAST_EXCEPTION,值为AuthenticationException
SpringBoot集成SpringSecurity(3)-----异常处理_第6张图片
至此 Spring security 完成了异常处理,总结一下流程:

–> AbstractAuthenticationProcessingFilter.doFilter()

–> AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication()

–> SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure()

–> SimpleUrlAuthenticationFailureHandler.saveException()

三、处理异常

1、指定URL,WebSecurityConfig中添加failureUrl("login/error")
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            // 如果有允许匿名的url,填在下面
//                .antMatchers().permitAll()
            .anyRequest().authenticated()
            .and()
            // 设置登陆页
            .formLogin().loginPage("/login")
            // 设置登陆成功页
            .defaultSuccessUrl("/").permitAll()
            // 登录失败Url
            .failureUrl("/login/error")
            // 自定义登陆用户名和密码参数,默认为username和password
//                .usernameParameter("username")
//                .passwordParameter("password")
            .and()
            .logout().permitAll()
            // 自动登录
            .and().rememberMe()
                .tokenRepository(persistentTokenRepository())
                // 有效时间:单位s
                .tokenValiditySeconds(60)
                .userDetailsService(userDetailsService);

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

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

我们首先获取了 session 中的 SPRING_SECURITY_LAST_EXCEPTION。 为了演示,简单的将异常信息返回给页面。运行程序,当我们输入错误密码时:
SpringBoot集成SpringSecurity(3)-----异常处理_第7张图片

你可能感兴趣的:(Spring,Boot,SpringSecurity)