东北亚科技园里有做网站的吗,百度网站地图在线生成,wordpress二级栏目,win8导航网站模板目录 1. 原理2. 组件3. ExceptionTranslationFilter3.1 默认过滤器顺序3.2 ExceptionTranslationFilter源码3.2.1 AuthenticationException异常3.2.2 AccessDeniedException异常 总结 1. 原理
Spring Security 异常处理的原理是通过一系列的异常处理器来处理在安全验证和授权过… 目录 1. 原理2. 组件3. ExceptionTranslationFilter3.1 默认过滤器顺序3.2 ExceptionTranslationFilter源码3.2.1 AuthenticationException异常3.2.2 AccessDeniedException异常 总结 1. 原理
Spring Security 异常处理的原理是通过一系列的异常处理器来处理在安全验证和授权过程中可能出现的异常。当发生异常时Spring Security会根据异常的类型和配置的处理器来确定如何处理异常。
异常处理的原理可以概括为以下几个步骤 认证过程中的异常处理在用户进行身份验证时可能会发生各种异常例如用户名或密码错误、账户锁定等。Spring Security使用AuthenticationManager来处理认证过程中的异常根据异常类型和配置的AuthenticationProvider来确定如何处理异常。 授权过程中的异常处理在用户通过认证后访问受保护资源时可能会发生授权异常例如用户没有足够的权限访问资源。Spring Security使用AccessDecisionManager来处理授权过程中的异常根据异常类型和配置的AccessDecisionVoter来确定如何处理异常。 异常转换和处理Spring Security还提供了ExceptionTranslationFilter来处理身份验证和授权过程中的异常。该过滤器会捕获异常并根据异常类型和配置的处理器例如AuthenticationEntryPoint和AccessDeniedHandler来进行适当的转换和处理。AuthenticationEntryPoint用于处理未经身份验证的请求AccessDeniedHandler用于处理已经身份验证但无权访问资源的请求。
2. 组件
在Spring Security中异常处理通常涉及以下几个关键组件 AuthenticationEntryPoint认证入口点用于处理未经身份验证的请求。当用户尝试访问受保护的资源时如果尚未进行身份验证AuthenticationEntryPoint将负责返回相应的响应例如要求用户进行身份验证或返回错误消息。 AccessDeniedHandler访问拒绝处理器用于处理已经身份验证但无权访问受保护资源的请求。如果用户已经通过身份验证但没有足够的权限访问某个资源AccessDeniedHandler将负责返回相应的响应例如返回自定义的错误页面或错误消息。 ExceptionTranslationFilter异常转换过滤器作为过滤器链中的一个关键组件ExceptionTranslationFilter负责捕获Spring Security中的异常并将其转换为适当的响应。它使用AuthenticationEntryPoint和AccessDeniedHandler来处理不同类型的异常并提供合适的响应。
通过配置这些组件您可以自定义异常处理的行为以满足您的应用程序需求。您可以指定自定义的AuthenticationEntryPoint和AccessDeniedHandler并将它们与Spring Security的过滤器链进行集成以实现自定义的异常处理逻辑。
3. ExceptionTranslationFilter
当身份验证失败或访问被拒绝时ExceptionTranslationFilter会拦截相应的异常并根据异常的类型和配置的处理器来进行适当的处理。它根据异常类型分别使用AuthenticationEntryPoint和AccessDeniedHandler来处理不同的异常情况。
3.1 默认过滤器顺序
过滤器链在初始化的时候会默认加载好一些默认的过滤器其中就包括ExceptionTranslationFilter过滤器。ExceptionTranslationFilter在过滤器链倒数第二个最后一个是FilterSecurityInterceptor。FilterSecurityInterceptor是用来获取所有配置资源的访问授权信息根据SecurityContextHolder中存储的用户信息来决定其是否有权限。
3.2 ExceptionTranslationFilter源码 //问拒绝处理 就是你要访问某个资源但是当你没有访问权限时就会抛出异常在此类中进行处理。private AccessDeniedHandler accessDeniedHandler new AccessDeniedHandlerImpl();//顾名思义身份验证入口主要用来判断你的身份凡是在身份认证过程中发生的错误private AuthenticationEntryPoint authenticationEntryPoint;//用以判断SecurityContextHolder中所存储信息 判断上下文中有无用户信息来抛出异常private AuthenticationTrustResolver authenticationTrustResolver new AuthenticationTrustResolverImpl();这是此类中的三个比较重要的私有字段其中accessDeniedHandler用来处理权限异常authenticationEntryPoint用来处理认证异常authenticationTrustResolver用以判断SecurityContextHolder中所存储信息 判断上下文中有无用户信息来抛出异常。其中accessDeniedHandler和authenticationEntryPoint异常处理在ExceptionTranslationFilter过滤器中处理。 private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws IOException, ServletException {try {//执行下一个过滤器逻辑也就是SecurityContextHolder过滤器。chain.doFilter(request, response);}catch (IOException ex) {throw ex;}catch (Exception ex) {// Try to extract a SpringSecurityException from the stacktrace//获取全部异常Throwable[] causeChain this.throwableAnalyzer.determineCauseChain(ex);//判断异常的类型 是否为AuthenticationExceptionRuntimeException securityException (AuthenticationException) this.throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain);if (securityException null) {//判断是否为AccessDeniedExceptionsecurityException (AccessDeniedException) this.throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class, causeChain);}//如果不是上边两个异常继续抛出说明此过滤器只处理AuthenticationException和AccessDeniedException异常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);}}chain.doFilter(request, response)会执行执行下一个过滤器逻辑也就是SecurityContextHolder过滤器。当用户未认证或者接口未授权时会被catch到执行异常处理。处理报错的核心逻辑在handleSpringSecurityException()方法中。 private void handleSpringSecurityException(HttpServletRequest request, HttpServletResponse response,FilterChain chain, RuntimeException exception) throws IOException, ServletException {if (exception instanceof AuthenticationException) {//处理AuthenticationException异常handleAuthenticationException(request, response, chain, (AuthenticationException) exception);}else if (exception instanceof AccessDeniedException) {//处理AccessDeniedException异常handleAccessDeniedException(request, response, chain, (AccessDeniedException) exception);}}异常分为两部分handleAuthenticationException处理AuthenticationException异常handleAccessDeniedException处理AccessDeniedException异常。
3.2.1 AuthenticationException异常 private void handleAuthenticationException(HttpServletRequest request, HttpServletResponse response,FilterChain chain, AuthenticationException exception) throws ServletException, IOException {this.logger.trace(Sending to authentication entry point since authentication failed, exception);sendStartAuthentication(request, response, chain, exception);}protected void sendStartAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,AuthenticationException reason) throws ServletException, IOException {// SEC-112: Clear the SecurityContextHolders Authentication, as the// existing Authentication is no longer considered validSecurityContextHolder.getContext().setAuthentication(null);this.requestCache.saveRequest(request, response);//调用authenticationEntryPoint子类的commence方法 我们自定义authenticationEntryPoint的子类this.authenticationEntryPoint.commence(request, response, reason);}可以看到最终会调用AuthenticationEntryPoint的commence方法。AuthenticationEntryPoint是一个接口有默认的实现类同时我们也可以自定义authenticationEntryPoint。
自定义authenticationEntryPoint
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {Overridepublic void commence(HttpServletRequest request,HttpServletResponse response,AuthenticationException authException) throws IOException {// 用户自定义返回}
}
3.2.2 AccessDeniedException异常 private void handleAccessDeniedException(HttpServletRequest request, HttpServletResponse response,FilterChain chain, AccessDeniedException exception) throws ServletException, IOException {Authentication authentication SecurityContextHolder.getContext().getAuthentication();//是否是游客登录boolean isAnonymous this.authenticationTrustResolver.isAnonymous(authentication);//如果是游客登录或者是rememberMe用户则重新登录if (isAnonymous || this.authenticationTrustResolver.isRememberMe(authentication)) {if (logger.isTraceEnabled()) {logger.trace(LogMessage.format(Sending %s to authentication entry point since access is denied,authentication), exception);}//重新登录sendStartAuthentication(request, response, chain,new InsufficientAuthenticationException(this.messages.getMessage(ExceptionTranslationFilter.insufficientAuthentication,Full authentication is required to access this resource)));}else {if (logger.isTraceEnabled()) {logger.trace(LogMessage.format(Sending %s to access denied handler since access is denied, authentication),exception);}//执行我们的权限认证错误自定义逻辑this.accessDeniedHandler.handle(request, response, exception);}}此代码最终调用的是AccessDeniedHandler的handle方法同样的AccessDeniedHandler是接口同时有默认实现类也可以自定义实现。
自定义AccessDeniedHandler
public class MyAccessDeniedHandler implements AccessDeniedHandler {Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {//用户自定义实现}
}总结 首先ExceptionTranslationFilter 调用 FilterChain.doFilter(request, response) 来调用应用程序的其他过滤器。 如果用户没有被认证或者是一个 AuthenticationException那么就开始认证SecurityContextHolder 被清理掉。HttpServletRequest 被保存起来这样一旦认证成功它就可以用来重放原始请求。 AuthenticationEntryPoint 用于请求客户的凭证。例如它可以重定向到一个登录页面或发送一个 WWW-Authenticate 头。 如果是 AccessDeniedException那么就是 Access Denied。AccessDeniedHandler 被调用来处理拒绝访问access denied。