4

I have implemented a custom 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");

    }
}

And configured it in 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();
}

I am using @PostAuthorize with a custom PermissionEvaluator

The PermissionEvaluator is working, but the AccessDeniedHandler is never called. Instead I am only getting the stacktrace of the Access Denied exception.

thanks for the Help.

EDIT: Added Stacktrace

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
bwright
  • 896
  • 11
  • 29
  • Hope in your case this happens when the user is already logged in but does not have access to certain resources due to authorization levels. right? – Mudassar Jun 26 '15 at 13:27
  • yes. user is logged in but tries to access a resource he has no access to. – bwright Jun 26 '15 at 13:29

5 Answers5

2

Ok It seems to be working when I change

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

To

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

Anyone may elaborate on why this is the behaviour? I would expect the 403 error page to be displayed and the stack trace in the log.

bwright
  • 896
  • 11
  • 29
  • check your code there should be some logical checks like the code given below 'FacesContext facesContext = FacesContext.getCurrentInstance(); Application application = facesContext.getApplication(); if (application.getProjectStage() == ProjectStage.Development) { // Define development settings } or FacesContext facesContext = FacesContext.getCurrentInstance(); if (facesContext.isProjectStage(ProjectStage.Development)) { // Define development settings }' – Mudassar Jun 29 '15 at 12:18
1

In my case the problem was that in addition to my CustomAccessDeniedHandler there was also a global resource exception handler with @ControllerAdvice. I solved this by rethrowing the exception in the global handler (as advised here https://github.com/spring-projects/spring-security/issues/6908), then my CustomAccessDeniedHandler gets executed.

@ControllerAdvice
public class ResourceExceptionHandler {
...
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity accessDeniedException(AccessDeniedException e) throws AccessDeniedException {
        log.info(e.toString());
        throw e;
    }
...
}
Jan Tomášek
  • 135
  • 10
0

1.You might want to set error page like this in your AccessDeniedHandler

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

Because the exception is valid but it is unable to find the page hence setting here might help

2. If everything fails you can also you can try this approach where in you can use the url pattern

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

Error page will always start with "/"

@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. In addition to above you can still use the custom AccessDeniedHandler by simply map it via a bean config

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

or

.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");

    }
}
Mudassar
  • 3,135
  • 17
  • 22
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/81845/discussion-between-bwright-and-mudassar). – bwright Jun 29 '15 at 08:50
  • Also what are you using for MVC ? in case of spring mvc there are chances where in the search for the bean happens inside the dispatcher, so need to drill down if the the /accessDeniedPage.htm is being searched in your mvc mapper instead of the securty mapper – Mudassar Jun 29 '15 at 08:54
0

WebSecurityConfigurerAdapter

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

i think you need to pick your own MyAccessDeniedHandler() here

prsmax
  • 223
  • 1
  • 7
  • Sorry typo in my code above. It actually says `.accessDeniedHandler(new MyAccessDeniedHandler())` – bwright Jun 26 '15 at 13:42
0

I faced the same issue. My custom AccessDeniedHandler was not being triggered. So I marked the AuthenticationEntryPoint class as @ControllerAdvice and added a new function with the annotation @ExceptionHandler . This is working for me now. You can see the complete code here

emilpmp
  • 1,716
  • 17
  • 32