03. Spring Security 異常處理


03. Spring Security 異常處理

參考:

https://blog.csdn.net/yuanlaijike/article/details/80250389

不知道你有沒有注意到,當我們登陸失敗時候,Spring security 幫我們跳轉到了 /login?error Url,奇怪的是不管是控制台還是網頁上都沒有打印錯誤信息。

這是因為首先 /login?error 是 Spring security 默認的失敗 Url,其次如果你不手動處理這個異常,這個異常是不會被處理的

#常見異常

我們先來列舉下一些 Spring Security 中常見的異常:

  • UsernameNotFoundException(用戶不存在)

  • DisabledException(用戶已被禁用)

  • BadCredentialsException(壞的憑據)

  • LockedException(賬戶鎖定)

  • AccountExpiredException (賬戶過期)

  • CredentialsExpiredException(證書過期)

以上列出的這些異常都是 AuthenticationException 的子類,然后我們來看看 Spring security 如何處理 AuthenticationException 異常的。

#源碼分析

AbstractAuthenticationProcessingFilterdoFilter()上打一個斷點

發現try-catch捕捉了attemptAuthentication(request, response);拋出的異常

並執行了unsuccessfulAuthentication(request, response, failed);

然后將異常交給SimPleUrlAuthenticationFailureHandeler

轉到方法能明顯的看到發送了/login?error請求

如果沒有是指defaultFailureUrl直接返回UNAUTHORIZED(401)

然后執行saveException(request, exception)

然后判斷 forwardToDestination ,即是否是服務器跳轉,默認使用重定向即客戶端跳轉。

這里可以發現設置了key為SPRING_SECURITY_LAST_EXCEPTION, value為AuthenticationException

到session域中, 所以我們也就可以通過SPRING_SECURITY_LAST_EXCEPTION獲取到對應的exception的值

#處理異常

方法一

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .successForwardUrl("/")
                //登入失敗跳轉url,重定向
                .failureUrl("/fail")
                .and()
                .logout().permitAll()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login")
                .clearAuthentication(true)
                .invalidateHttpSession(true)
                .deleteCookies("JSESSIONID")
                .and()
                .rememberMe()
                .tokenValiditySeconds(60)
                .tokenRepository(persistentTokenRepository())
                .userDetailsService(userDetailsService)
                .and()
                .csrf()
                .disable();
    }
    @ResponseBody
	@GetMapping("/fail")
    public Object fail(HttpServletRequest req, HttpServletResponse resp){
        log.info("failure into this ");
        //設置編碼防止亂碼
        resp.setContentType("application/json;charset=utf-8");
        AuthenticationException exception = (AuthenticationException)
                req.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
        return exception;
    }

方法二(推薦)

修改配置類

.successForwardUrl("/")

POST方式請求轉發

    @ResponseBody
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @PostMapping("/fail")
    public String fail() {
        return "賬號或密碼錯誤";
    }

方法三

修改配置類

.failureHandler(failureHandler())

使用自定的handler, 需要將該類注入到ioc中

  • 返回Json
public class FailureHandler implements AuthenticationFailureHandler {
    @Autowired
    ObjectMapper mapper;
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().print(mapper.writeValueAsString(exception));
    }
}
  • 重定向
public class FailureHandler implements AuthenticationFailureHandler {
    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
    @Autowired
    ObjectMapper mapper;
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        redirectStrategy.sendRedirect(request,response,"/fail");
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM