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,是什麼?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章