Spring Security(1-7) Spring Security 中自定義異常處理


Spring Security 中自定義異常處理

我們最常見的 UsernamePasswordAuthenticationFilter 和 FilterSecurityInterceptor 這 2 個 Filter 在拋異常(和處理)的邏輯是不一樣的:

  • UsernamePasswordAuthenticationFilter 在做認證時,如果拋出了異常(例如認證不通過時),是它自己 try ... catch ... 處理掉了。

  • FilterSecurityInterceptor 在做鑒權時,如果拋出了異常(例如用戶未登錄或用戶權限不夠),它是將異常拋給了它前面的 ExceptionTranslationFilter ,由 ExceptionTranslationFilter 來 try ... catch ... 處理。

#1. 認證環節的異常處理

Spring Security 的認證工作是由 UsernamePasswordAuthenticationFilter 處理的。查看它( 和它的父類 AbstractAuthenticationProcessingFilter )的源碼,我們可以看到:

  • 當認證通過時,會執行它( 繼承自父類 )的 successfulAuthentication 方法。successfulAuthentication 的默認行為(之前講過):繼續用戶原本像訪問的 URI 。

    另外,你可以通過 http.successHandler(...) 來 “覆蓋” 默認的成功行為。

  • 當認證不通過時,會執行它( 繼承自父類 )的 unsuccessfulAuthentication 方法。unsuccessfulAuthentication 的默認行為是再次顯示登陸頁面,並在頁面上提示用戶名密碼錯誤。

    另外,你可以通過 http.failureHandler(...) 來 “覆蓋” 默認的失敗行為。

前面章節有講過,這里不再贅述了。

#2. 鑒權環節的異常處理

Spring Security 的認證工作是由 FilterSecurityInterceptor 處理的。FilterSecurityInterceptor 會拋出 2 種異常:

  1. 在用戶 “該登錄而未登錄” 時,拋出 AuthenticationException 異常;

    默認情況下,拋出 AuthenticationException 異常時,Spring Security 返回 401 錯誤:未授權(Unauthorized)。

  2. 在用戶 “權限不夠” 時,拋出 AccessDeniedException 異常。

    默認情況下,拋出 AccessDeniedException 異常時,Spring Security 返回 403 錯誤:被拒絕(Forbidden)訪問

在 Spring Security 配置中可以通過 http.exceptionHandling() 配置方法用來自定義鑒權環節的異常處理。配置風格如下:

http.exceptionHandling() .authenticationEntryPoint(...) .accessDeniedHandler(...); 
Copied!

其中:

  • AuthenticationEntryPoint 該類用來統一處理 AuthenticationException 異常;

  • AccessDeniedHandler 該類用來統一處理 AccessDeniedException 異常。

實現 AuthenticationEntryPoint 接口
實現 AccessDeniedHandler 接口
public class SimpleAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { HashMap<String, String> map = new HashMap<>(2); map.put("uri", request.getRequestURI()); map.put("msg", "你是不是沒登錄?"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setCharacterEncoding(StandardCharsets.UTF_8.toString()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); ObjectMapper objectMapper = new ObjectMapper(); String resBody = objectMapper.writeValueAsString(map); PrintWriter printWriter = response.getWriter(); printWriter.print(resBody); printWriter.flush(); printWriter.close(); } } 
 


免責聲明!

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



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