org.springframework.security.web.AuthenticationEntryPoint在spring-security-web裏面,分析的版本是5.0。java
List-1web
package org.springframework.security.web; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; public interface AuthenticationEntryPoint { void commence(HttpServletRequest var1, HttpServletResponse var2, AuthenticationException var3) throws IOException, ServletException; }
當用戶請求了一個受保護的資源,可是用戶沒有經過認證,那麼拋出異常,AuthenticationEntryPoint. Commence(..)就會被調用。這個對應的代碼在ExceptionTranslationFilter中,以下List-2,當ExceptionTranslationFilter catch到異常後,就會間接調用AuthenticationEntryPoint。spring
List-2app
public class ExceptionTranslationFilter extends GenericFilterBean { private AuthenticationEntryPoint authenticationEntryPoint; ...... public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)res; try { chain.doFilter(request, response); this.logger.debug("Chain processed normally"); } catch (IOException var9) { throw var9; } catch (Exception var10) { ...... this.handleSpringSecurityException(request, response, chain, (RuntimeException)ase); } } private void handleSpringSecurityException(HttpServletRequest request, HttpServletResponse response, FilterChain chain, RuntimeException exception) throws IOException, ServletException { ...... this.sendStartAuthentication(request, response, chain, (AuthenticationException)exception); ...... } protected void sendStartAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, AuthenticationException reason) throws ServletException, IOException { SecurityContextHolder.getContext().setAuthentication((Authentication)null); this.requestCache.saveRequest(request, response); this.logger.debug("Calling Authentication entry point."); this.authenticationEntryPoint.commence(request, response, reason); } ......
因此,咱們能夠經過定義AuthenticationEntryPoint統一處理拋出的異常,以下List-3ide
List-3this
@Component @AllArgsConstructor public class CustomAuthExceptionEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { response.setCharacterEncoding(CommonConstants.UTF8); response.setContentType(CommonConstants.CONTENT_TYPE); R<String> result = new R<>(); result.setCode(HttpStatus.HTTP_UNAUTHORIZED); if (authException != null) { result.setMsg("error"); result.setData(authException.getMessage()); } response.setStatus(HttpStatus.HTTP_UNAUTHORIZED); PrintWriter printWriter = response.getWriter(); printWriter.append(JSONObject.toString(result)); } }