1. 结论
**
AuthenticationEntryPoint 用来解决匿名用户访问无权限资源时的异常
AccessDeineHandler 用来解决认证过的用户访问无权限资源时的异常
2. AuthenticationEntryPoint
AuthenticationEntryPoint 是 Spring Security Web 一个概念模型接口,顾名思义,他所建模的概念是:“认证入口点”。
它在用户请求处理过程中遇到认证异常时,被 ExceptionTranslationFilter 用于开启特定认证方案 (authentication schema) 的认证流程。
该接口只定义了一个方法 :
void commence(HttpServletRequest request, HttpServletResponse response,AuthenticationException authException) throws IOException, ServletException;
这里参数 request 是遇到了认证异常 authException 用户请求,response 是将要返回给客户的相应,方法 commence 实现,也就是相应的认证方案逻辑会修改 response 并返回给用户引导用户进入认证流程。
当用户请求了一个受保护的资源,但是用户没有通过认证,那么抛出异常,AuthenticationEntryPoint.Commence(..)就会被调用。这个对应的代码在ExceptionTranslationFilter中,如下,当ExceptionTranslationFilter catch到异常后,就会间接调用AuthenticationEntryPoint。
public class ExceptionTranslationFilter extends GenericFilterBean {private AuthenticationEntryPoint authenticationEntryPoint;......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);this.logger.debug("Chain processed normally");} catch (IOException var9) {throw var9;} catch (Exception var10) {......this.handleSpringSecurityException(request, response, chain, (RuntimeException)ase);}}private void handleSpringSecurityException(HttpServletRequest request, HttpServletResponse response, FilterChain chain, RuntimeException exception) throws IOException, ServletException {......this.sendStartAuthentication(request, response, chain, (AuthenticationException)exception);......}protected void sendStartAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, AuthenticationException reason) throws ServletException, IOException {SecurityContextHolder.getContext().setAuthentication((Authentication)null);this.requestCache.saveRequest(request, response);this.logger.debug("Calling Authentication entry point.");this.authenticationEntryPoint.commence(request, response, reason);}......
匿名用户访问某个接口时
/*** 认证失败处理类 返回未授权* 用来解决匿名用户访问无权限资源时的异常*/@Componentpublic class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)throws IOException {response.setCharacterEncoding("utf-8");response.setContentType("text/javascript;charset=utf-8");response.getWriter().print(JSONObject.toJSONString(RestMsg.error("没有访问权限!")));}}
3. AccessDeniedHandler
AccessDeniedHandler 仅适用于已通过身份验证的用户。未经身份验证的用户的默认行为是重定向到登录页面(或适用于正在使用的身份验证机制的任何内容)。
已经授权但是没有访问权限
/*** 认证失败处理类 返回未授权* 用来解决认证过的用户访问无权限资源时的异常*/@Componentpublic class CustomAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response,AccessDeniedException accessDeniedException) throws IOException, ServletException {response.setCharacterEncoding("utf-8");response.setContentType("text/javascript;charset=utf-8");response.getWriter().print(JSONObject.toJSONString(RestMsg.error("没有访问权限!")));}}
4. 配置
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate CustomAuthenticationEntryPoint authenticationEntryPoint;@Autowiredprivate CustomAccessDeniedHandler customAccessDeniedHandler;// 省略部分代码@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {httpSecurity// 认证失败处理类.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(customAccessDeniedHandler);}// 省略部分代码}
