文章目录
前言
本文主要研究异常处理过滤器 ExceptionTranslationFilter
一、ExceptionTranslationFilter 做了什么
这就不得不提另外一个过滤器 -> 鉴权过滤器
AuthorizationFilter,ExceptionTranslationFilter是用来处理鉴权失败抛出的异常的过滤器
二、源码解析
ExceptionTranslationFilter#doFilter
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
// 直接执行下面的过滤器, 这个过滤器后面就只剩一个 AuthorizationFilter
chain.doFilter(request, response);
}
// 抛出异常之后处理
// IO异常直接抛出
catch (IOException ex) {
throw ex;
}
catch (Exception ex) {
// Try to extract a SpringSecurityException from the stacktrace
Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(ex);
// 找到抛出的到底是什么异常
RuntimeException securityException = (AuthenticationException) this.throwableAnalyzer
.getFirstThrowableOfType(AuthenticationException.class, causeChain);
if (securityException == null) {
securityException = (AccessDeniedException) this.throwableAnalyzer
.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
}
if (securityException == null) {
rethrow(ex);
}
if (response.isCommitted()) {
throw new ServletException("Unable to handle the Spring Security Exception "
+ "because the response is already committed.", ex);
}
// 抛出异常后的处理
handleSpringSecurityException(request, response, chain, securityException);
}
}
ExceptionTranslationFilter#handleSpringSecurityException
private void handleSpringSecurityException(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, RuntimeException exception) throws IOException, ServletException {
// 如果是认证异常, 最后会重定向到登录页, 但是我看 AuthorizationFilter 也没有抛出这个异常, 可能是没有看完, 后面还待研究
if (exception instanceof AuthenticationException) {
handleAuthenticationException(request, response, chain, (AuthenticationException) exception);
}
// 访问被拒绝, 也就是没有权限的异常
else if (exception instanceof AccessDeniedException) {
handleAccessDeniedException(request, response, chain, (AccessDeniedException) exception);
}
}
ExceptionTranslationFilter#handleAuthenticationException
private void handleAuthenticationException(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, AuthenticationException exception) throws ServletException, IOException {
// 重定向到登录页
sendStartAuthentication(request, response, chain, exception);
}
ExceptionTranslationFilter#handleAccessDeniedException
private void handleAccessDeniedException(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, AccessDeniedException exception) throws ServletException, IOException {
Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
boolean isAnonymous = this.authenticationTrustResolver.isAnonymous(authentication);
// 如果是匿名, 重定向到登录页
if (isAnonymous || this.authenticationTrustResolver.isRememberMe(authentication)) {
// 重定向到登录页
sendStartAuthentication(request, response, chain, xxx);
}
else {
// 鉴权失败处理器处理: 一般是返回给浏览器一个 403 的状态码
this.accessDeniedHandler.handle(request, response, exception);
}
}

1万+

被折叠的 条评论
为什么被折叠?



