Spring Security(1-7) Spring Security 中自定义异常处理


Spring Security 中自定义异常处理

我们最常见的 UsernamePasswordAuthenticationFilter 和 FilterSecurityInterceptor 这 2 个 Filter 在抛异常(和处理)的逻辑是不一样的:

  • UsernamePasswordAuthenticationFilter 在做认证时,如果抛出了异常(例如认证不通过时),是它自己 try ... catch ... 处理掉了。

  • FilterSecurityInterceptor 在做鉴权时,如果抛出了异常(例如用户未登录或用户权限不够),它是将异常抛给了它前面的 ExceptionTranslationFilter ,由 ExceptionTranslationFilter 来 try ... catch ... 处理。

#1. 认证环节的异常处理

Spring Security 的认证工作是由 UsernamePasswordAuthenticationFilter 处理的。查看它( 和它的父类 AbstractAuthenticationProcessingFilter )的源码,我们可以看到:

  • 当认证通过时,会执行它( 继承自父类 )的 successfulAuthentication 方法。successfulAuthentication 的默认行为(之前讲过):继续用户原本像访问的 URI 。

    另外,你可以通过 http.successHandler(...) 来 “覆盖” 默认的成功行为。

  • 当认证不通过时,会执行它( 继承自父类 )的 unsuccessfulAuthentication 方法。unsuccessfulAuthentication 的默认行为是再次显示登陆页面,并在页面上提示用户名密码错误。

    另外,你可以通过 http.failureHandler(...) 来 “覆盖” 默认的失败行为。

前面章节有讲过,这里不再赘述了。

#2. 鉴权环节的异常处理

Spring Security 的认证工作是由 FilterSecurityInterceptor 处理的。FilterSecurityInterceptor 会抛出 2 种异常:

  1. 在用户 “该登录而未登录” 时,抛出 AuthenticationException 异常;

    默认情况下,抛出 AuthenticationException 异常时,Spring Security 返回 401 错误:未授权(Unauthorized)。

  2. 在用户 “权限不够” 时,抛出 AccessDeniedException 异常。

    默认情况下,抛出 AccessDeniedException 异常时,Spring Security 返回 403 错误:被拒绝(Forbidden)访问

在 Spring Security 配置中可以通过 http.exceptionHandling() 配置方法用来自定义鉴权环节的异常处理。配置风格如下:

http.exceptionHandling() .authenticationEntryPoint(...) .accessDeniedHandler(...); 
Copied!

其中:

  • AuthenticationEntryPoint 该类用来统一处理 AuthenticationException 异常;

  • AccessDeniedHandler 该类用来统一处理 AccessDeniedException 异常。

实现 AuthenticationEntryPoint 接口
实现 AccessDeniedHandler 接口
public class SimpleAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { HashMap<String, String> map = new HashMap<>(2); map.put("uri", request.getRequestURI()); map.put("msg", "你是不是没登录?"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setCharacterEncoding(StandardCharsets.UTF_8.toString()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); ObjectMapper objectMapper = new ObjectMapper(); String resBody = objectMapper.writeValueAsString(map); PrintWriter printWriter = response.getWriter(); printWriter.print(resBody); printWriter.flush(); printWriter.close(); } } 
 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM