【问题标题】:Custom AccessDeniedHandler not called未调用自定义 AccessDeniedHandler
【发布时间】:2015-09-13 11:00:12
【问题描述】:

我已经实现了一个自定义的 AccessDeniedHandler:

public class MyAccessDeniedHandler implements AccessDeniedHandler {


    @Override
    public void handle(HttpServletRequest request,
        HttpServletResponse response,
        AccessDeniedException accessDeniedException) throws IOException,
        ServletException {

        System.err.println("Access DENIED ");
        response.sendRedirect("/public/error.xhtml");

    }
}

并在WebSecurityConfigurerAdapter进行配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/docs/**", "/public/**", "/javax.faces.resource/**", "/index.html", "/uploads/**").permitAll()
            .anyRequest().authenticated()
        .and()
            .formLogin()
            .loginPage("/public/login.xhtml")
            .failureUrl("/public/login.xhtml?l=error")
            .defaultSuccessUrl("/public/login.xhtml?l=success")
            .permitAll()
        .and()
            .logout()
            .permitAll()
            .deleteCookies()
            .logoutSuccessUrl("/public/login.xhtml?faces-redirect=true&l=logout")
            .invalidateHttpSession(true)
        .and()
            .exceptionHandling()
            .accessDeniedHandler(new MyAccessDeniedHandler())
        .and()
            .csrf()
            .disable();
}

我正在使用 @PostAuthorize 和自定义 PermissionEvaluator

PermissionEvaluator 正在工作,但从未调用过 AccessDeniedHandler。相反,我只得到 Access Denied 异常的堆栈跟踪。

感谢您的帮助。

编辑:添加堆栈跟踪

javax.el.ELException: /secured/organisation/ou.xhtml @17,67 value="#{ouBean.activeOU.name}": org.springframework.security.access.AccessDeniedException: Access is denied
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
at javax.faces.component.UICommand.getValue(UICommand.java:218)
at org.primefaces.component.menu.BaseMenuRenderer.encodeMenuItemContent(BaseMenuRenderer.java:249)
at org.primefaces.component.menu.BaseMenuRenderer.encodeMenuItem(BaseMenuRenderer.java:215)
at org.primefaces.component.breadcrumb.BreadCrumbRenderer.encodeMarkup(BreadCrumbRenderer.java:75)
at org.primefaces.component.menu.BaseMenuRenderer.encodeEnd(BaseMenuRenderer.java:113)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1863)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:889)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:456)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at org.ocpsoft.rewrite.faces.RewriteViewHandler.renderView(RewriteViewHandler.java:186)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:178)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:205)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:168)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.el.ELException: org.springframework.security.access.AccessDeniedException: Access is denied
at javax.el.BeanELResolver.getValue(BeanELResolver.java:368)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
at com.sun.el.parser.AstValue.getValue(AstValue.java:140)
at com.sun.el.parser.AstValue.getValue(AstValue.java:204)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226)
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
... 96 more
Caused by: org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.expression.method.ExpressionBasedPostInvocationAdvice.after(ExpressionBasedPostInvocationAdvice.java:62)
at org.springframework.security.access.prepost.PostInvocationAdviceProvider.decide(PostInvocationAdviceProvider.java:41)
at org.springframework.security.access.intercept.AfterInvocationProviderManager.decide(AfterInvocationProviderManager.java:81)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.afterInvocation(AbstractSecurityInterceptor.java:316)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:73)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at de.uni_freiburg.brainlinks_braintools.rais.service.OrganisationalUnitService$$EnhancerBySpringCGLIB$$c32d2659.getById(<generated>)
at de.uni_freiburg.brainlinks_braintools.rais.model.OrganisationalUnit.getById(OrganisationalUnit.java:218)
at de.uni_freiburg.brainlinks_braintools.rais.managedBeans.OrganisationalUnitBean.getActiveOU(OrganisationalUnitBean.java:168)
at sun.reflect.GeneratedMethodAccessor320.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:363)
... 103 more

【问题讨论】:

  • 希望在您的情况下,当用户已经登录但由于授权级别而无权访问某些资源时会发生这种情况。对吗?
  • 是的。用户已登录但尝试访问他无权访问的资源。

标签: java spring spring-security


【解决方案1】:

好的,当我更改时它似乎正在工作

servletContext.setInitParameter("javax.faces.PROJECT_STAGE",
            "Development");

servletContext.setInitParameter("javax.faces.PROJECT_STAGE",
            "Production");

任何人都可以详细说明为什么这是这种行为?我希望显示 403 错误页面和日志中的堆栈跟踪。

【讨论】:

  • 检查你的代码应该有一些逻辑检查,比如下面给出的代码 'FacesContext facesContext = FacesContext.getCurrentInstance();应用程序 application = facesContext.getApplication(); if (application.getProjectStage() == ProjectStage.Development) { // 定义开发设置 } 或 FacesContext facesContext = FacesContext.getCurrentInstance(); if (facesContext.isProjectStage(ProjectStage.Development)) { // 定义开发设置 }'
【解决方案2】:

就我而言,问题在于除了我的 CustomAccessDeniedHandler 之外,还有一个带有 @ControllerAdvice 的全局资源异常处理程序。我通过在全局处理程序中重新抛出异常解决了这个问题(这里建议 https://github.com/spring-projects/spring-security/issues/6908),然后我的 CustomAccessDeniedHandler 被执行。

@ControllerAdvice
public class ResourceExceptionHandler {
...
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity accessDeniedException(AccessDeniedException e) throws AccessDeniedException {
        log.info(e.toString());
        throw e;
    }
...
}

【讨论】:

    【解决方案3】:

    WebSecurityConfigurerAdapter

    .and()
    .exceptionHandling()
    .accessDeniedHandler(new AccessDeniedHandler())
    

    我认为你需要在这里选择自己的MyAccessDeniedHandler()

    【讨论】:

    • 对不起,我上面的代码中有错字。它实际上说.accessDeniedHandler(new MyAccessDeniedHandler())
    【解决方案4】:

    1.您可能想在 AccessDeniedHandler 中设置这样的错误页面

     public void setErrorPage(String errorPage) {
          ....
        }
    

    因为异常有效但无法找到页面,因此在此处设置可能会有所帮助

    2。如果一切都失败了,您也可以尝试这种方法,您可以在其中使用 url 模式

    .exceptionHandling().accessDeniedPage("/accessDeniedPage.htm")
    

    错误页面总是以“/”开头

    @Controller
    public class MyAccessDeniedHandler {
    
        @RequestMapping(value = "/accessDeniedPage.htm", method = RequestMethod.GET)
        public String redirectAccessDenied(Model model) throws IOException, ServletException {
            System.out.println(" Redirect Access Denied Handler!");
            return "myerrorpage";
        }
    }
    

    3。除了上述之外,您仍然可以通过简单地通过 bean 配置映射来使用自定义 AccessDeniedHandler

    .exceptionHandling().accessDeniedPage("/accessDeniedPage.htm")
     @Bean( name = "/accessDeniedPage.htm" )
        public AccessDeniedHandler  authenticationEntryPoint() {    
            return new MyAccessDeniedHandler();
        }
    

    .accessDeniedHandler( this.acessDeniedHandler() );
     @Bean( name = "/accessDeniedPage.htm" )
            public AccessDeniedHandler  accessDeniedHandler() {    
                return new MyAccessDeniedHandler();
            }
    
    public class MyAccessDeniedHandler implements AccessDeniedHandler {    
    
        @Override
        public void handle(HttpServletRequest request,
            HttpServletResponse response,
            AccessDeniedException accessDeniedException) throws IOException,
            ServletException {
    
            System.err.println("Access DENIED ");
            response.sendRedirect("/public/error.xhtml");
    
        }
    }
    

    【讨论】:

    • 另外,你在 MVC 中使用什么?在 spring mvc 的情况下,有可能在调度程序内部搜索 bean,因此如果在 mvc 映射器而不是安全映射器中搜索 /accessDeniedPage.htm,则需要深入研究
    【解决方案5】:

    我遇到了同样的问题。我的自定义 AccessDeniedHandler 没有被触发。所以我将 AuthenticationEntryPoint 类标记为 @ControllerAdvice 并添加了一个带有注释 @ExceptionHandler 的新函数。这现在对我有用。可以看完整代码here

    【讨论】:

      猜你喜欢
      • 2019-03-29
      • 2011-10-24
      • 2021-03-10
      • 1970-01-01
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多