13、spring security拦截器之ExceptionTranslationFilter

ExceptionTranslationFilter:异常处理,对AuthenticationException和AccessDeniedException进行处理

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);

      logger.debug("Chain processed normally");
   }
   catch (IOException ex) {
      throw ex;
   }
   catch (Exception ex) {
      // Try to extract a SpringSecurityException from the stacktrace
      Throwable[] causeChain = throwableAnalyzer.determineCauseChain(ex);
      RuntimeException ase = (AuthenticationException) throwableAnalyzer
            .getFirstThrowableOfType(AuthenticationException.class, causeChain);

      if (ase == null) {
         ase = (AccessDeniedException) throwableAnalyzer.getFirstThrowableOfType(
               AccessDeniedException.class, causeChain);
      }
       //这里主要是对AuthenticationException和AccessDeniedException异常类型进行相对应的操作
      if (ase != null) {
         if (response.isCommitted()) {
            throw new ServletException("Unable to handle the Spring Security Exception because the response is already committed.", ex);
         }
         handleSpringSecurityException(request, response, chain, ase);
      }
      else {
         // Rethrow ServletExceptions and RuntimeExceptions as-is
         if (ex instanceof ServletException) {
            throw (ServletException) ex;
         }
         else if (ex instanceof RuntimeException) {
            throw (RuntimeException) ex;
         }

         // Wrap other Exceptions. This shouldn't actually happen
         // as we've already covered all the possibilities for doFilter
         throw new RuntimeException(ex);
      }
   }
}

handleSpringSecurityException()

private void handleSpringSecurityException(HttpServletRequest request,
      HttpServletResponse response, FilterChain chain, RuntimeException exception)
      throws IOException, ServletException {
   if (exception instanceof AuthenticationException) {
      logger.debug(
            "Authentication exception occurred; redirecting to authentication entry point",
            exception);

      sendStartAuthentication(request, response, chain,
            (AuthenticationException) exception);
   }
   else if (exception instanceof AccessDeniedException) {
      Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
      if (authenticationTrustResolver.isAnonymous(authentication) || authenticationTrustResolver.isRememberMe(authentication)) {
         logger.debug(
               "Access is denied (user is " + (authenticationTrustResolver.isAnonymous(authentication) ? "anonymous" : "not fully authenticated") + "); redirecting to authentication entry point",
               exception);

         sendStartAuthentication(
               request,
               response,
               chain,
               new InsufficientAuthenticationException(
                  messages.getMessage(
                     "ExceptionTranslationFilter.insufficientAuthentication",
                     "Full authentication is required to access this resource")));
      }
      else {
         logger.debug(
               "Access is denied (user is not anonymous); delegating to AccessDeniedHandler",
               exception);
         //访问异常执行器,返回认证错误的json信息      
         accessDeniedHandler.handle(request, response,
               (AccessDeniedException) exception);
      }
   }
}

sendStartAuthentication()

protected void sendStartAuthentication(HttpServletRequest request,
      HttpServletResponse response, FilterChain chain,
      AuthenticationException reason) throws ServletException, IOException {
   // SEC-112: Clear the SecurityContextHolder's Authentication, as the
   // existing Authentication is no longer considered valid
   SecurityContextHolder.getContext().setAuthentication(null);
   //保存当前的请求,方便后续认证成功后跳回该请求
   requestCache.saveRequest(request, response);
   logger.debug("Calling Authentication entry point.");
   //重定向到登录页。实现类:LoginUrlAuthenticationEntryPoint
   authenticationEntryPoint.commence(request, response, reason);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值