Springsecurity之ExceptionTranslationFilter

    Springsecurity的版本是4.3.x,源码可以在Github上下载。

1、ExceptionTranslationFilter的doFilter

 ExceptionTranslationFilter是个异常过滤器,用来处理在认证授权过程中抛出的异常,ExceptionTranslationFilter后面的过滤器是FilterSecurityInterceptor。先上一张图,如下图1所示:

                                                              图1

  • 红框1中的,是调用Filter链中的后续Filter。
  • 如果图1中的操作抛出异常,就会来到红框2处,判断抛出的异常是否是AuthenticationException。
  • 如果抛出的异常不是AuthenticationException,即红框2的结果为null,那么就到红框3处,判断是否是AccessDeniedException。
  • 如果抛出的异常是AuthenticationException或者时AccessDeniedException,那么执行红框4处的代码。

2、ExceptionTranslationFilter的handleSpringSecurityException方法

下面来看handleSpringSecurityException的方法体,如下List-1所示

    List-1

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

				accessDeniedHandler.handle(request, response,
						(AccessDeniedException) exception);
			}
		}
	}
  1. 如果抛出的异常是AuthenticationException,则执行方法sendStartAuthentication
  2. 如果抛出的异常是AccessDeniedException,且从SecurityContextHolder.getContext().getAuthentication()得到的是AnonymousAuthenticationToken或者RememberMeAuthenticationToken,那么执行sendStartAuthentication
  3. 如果上面的第二点不满足,则执行accessDeniedHandler的handle方法

3、ExceptionTranslationFilter的sendStartAuthentication方法

    如下List-2所示,会调用authenticationEntryPoint的commence方法。

    List-2

	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.");
		authenticationEntryPoint.commence(request, response, reason);
	}

思考:

  1. 我们有时候会在xml配置中配置accessDeniedHandler,是在这里用到吗?
  2. List-2中使用到的authenticationEntryPoint,是什么?

猜你喜欢

转载自my.oschina.net/u/2518341/blog/2874735
今日推荐