V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
devswork
V2EX  ›  Java

SpringSecurity 的无权访问异常理器 AccessDeniedHandler 与统一异常处理器 DefaultHandlerExceptionResolver 冲突

  •  
  •   devswork · 2021-04-21 13:58:16 +08:00 · 438 次点击
    这是一个创建于 1072 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目使用 SpringSecurity 进行 API 权限控制,在项目中实现了 AccessDeniedHandler 接口用于被拒绝时的异常处理:

    @Slf4j
    @Component
    public class MyAccessDeniedHandler implements AccessDeniedHandler {
        @Override
        public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
            log.info("AccessDeniedHandler 异常....."); //打印被拒绝日志
            httpServletResponse.setContentType("text/json;charset=utf-8");
            httpServletResponse.getWriter().write(JSON.toJSONString(ResultGenerator.noPermission()));
        }
    
    }
    

    并且在 WebSecurityConfigurerAdapter 的 http 配置中配置了异常处理:

    @Bean
    public AccessDeniedHandler getAccessDeniedHandler() {
    	return new MyAccessDeniedHandler();
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    	// ....
    	
    	//异常处理
    	http.exceptionHandling().accessDeniedHandler(getAccessDeniedHandler());
    	
    	// ...
    }
    

    项目中还是用了统一异常处理器 DefaultHandlerExceptionResolver:

    @Slf4j
    @Component
    @ControllerAdvice
    public class MyGlobalExceptionHandler extends DefaultHandlerExceptionResolver {
    
        @ResponseBody
        @ExceptionHandler(Exception.class)
        public R defaultErrorHandler(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
    		
    	e.printStackTrace(); //打印堆栈
            log.info("DefaultHandlerExceptionResolver 统一异常处理器...");//打印异常日志
    		
        }
    }
    

    问题来了,当无权访问时,并不是执行 MyAccessDeniedHandler (尽管它已经在 SpringSecurity 中已经注册异常处理器),这个异常始终会在 MyGlobalExceptionHandler 中处理,打印了堆栈信息和异常日志:

    2021-04-21 13:52:30.226  INFO 32684 --- [io-18000-exec-2] c.d.m.s.TokenAuthenticationFilter        : TokenAuthenticationFilter...token = d72b29cbaa074cba99377cec73999575
    2021-04-21 13:52:30.235  INFO 32684 --- [io-18000-exec-2] c.d.mp.support.MyGlobalExceptionHandler  : DefaultHandlerExceptionResolver 统一异常处理器...
    2021-04-21 13:52:30.235  INFO 32684 --- [io-18000-exec-2] c.d.mp.support.MyGlobalExceptionHandler  : 无权限访问...http://127.0.0.1:18000/test/hello  R(code=403, data=null, message=没有权限访问, time=1618984350235)
    org.springframework.security.access.AccessDeniedException: 不允许访问
    	at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:73)
    	at org.springframework.security.access.intercept.AbstractSecurityInterceptor.attemptAuthorization(AbstractSecurityInterceptor.java:238)
    	at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:208)
    	at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:58)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
    	at com.dkdy.mp.controller.business.TestController$$EnhancerBySpringCGLIB$$fe1a52b5.hello(<generated>)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:498)
    	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)
    	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)
    	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
    	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060)
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
    	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    	..............
    

    如何让无权访问的异常被 MyAccessDeniedHandler 捕获处理,而不是让统一异常处理器来处理 SpringSecurity 的无权访问异常呢?

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3060 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 00:18 · PVG 08:18 · LAX 17:18 · JFK 20:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.