Results 1 to 8 of 8

Thread: access-denied-handler failing to redirect and causes a 404 Page Not Found

  1. #1
    Join Date
    Feb 2009
    Posts
    11

    Default access-denied-handler failing to redirect and causes a 404 Page Not Found

    HI there,

    I am having some issues with the access denied handler in my setup and i'm now tearing my hair out trying to resolve this.

    When i try and access a resource which I do not have permission for i want it to be handled by a custom handler that will make an audit log entry and then display our custom 403 error. The problem is that all i recieve is a 404 Page Not Found error.

    The error page itself is in a controller mapped by '/error/403' and this is displayed when accessed directly. I have also tried using a static jsp '/error.jsp' and this also displays fine when requested.

    My logs and spring config files are as follows:

    My application log:

    Code:
    16:50:17.278 [http-thread-pool-8181-(1)] [DEBUG] [o.s.s.w.a.ExceptionTranslationFilter] - Access is denied (user is not anonymous); delegating to AccessDeniedHandler
    org.springframework.security.access.AccessDeniedException: Access is denied
    	at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:71) ~[spring-security-core-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    	at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:203) ~[spring-security-core-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:106) ~[spring-security-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) ~[spring-security-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    .
    .
    .
    .
    Which is what i expected and this is what appears in my glassfish server log:
    (ps it is worth noting that when i log in with the correct user i do indeed get to the requested page)

    Code:
    [#|2010-12-09T16:50:17.278+0000|SEVERE|glassfish3.0.1|org.apache.jasper.servlet.JspServlet|_ThreadID=25;_ThreadName=Thread-1;|PWC6117: File "C:\glassfishv3\glassfish\domains\domain1\applications\java\admin\adminSecure" not found|#]
    My spring security configuration is as follows (I have my oid details held in another file):
    Code:
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:s="http://www.springframework.org/schema/security"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.4.xsd">
    
        <s:http use-expressions="true">
    
            <s:intercept-url pattern="/resources/**" filters="none" requires-channel="https"/>
            <s:intercept-url pattern="/logout" access="permitAll" requires-channel="https"/>
            <s:intercept-url pattern="/login**" access="permitAll" requires-channel="https"/>
            <s:intercept-url pattern="/admin/**" access="hasRole('APPS_ADMIN')" requires-channel="https"/>
            <s:intercept-url pattern="/**" access="hasAnyRole('APPS_USER','APPS_ADMIN')" requires-channel="https"/>
    
    
            <s:form-login login-page="/login"
                          login-processing-url="/app_security_check"
                          authentication-success-handler-ref="loginSuccessHandler"
                          authentication-failure-handler-ref="loginFailureHandler"/>
    
            <s:logout invalidate-session="true"
                      logout-url="/logout"
                      logout-success-url="/login?signout=true"/>
    
            <s:access-denied-handler ref="accessDeniedHandler"/>
            
            <!--<s:access-denied-handler error-page="/error.jsp" />-->        
            <!--<s:access-denied-handler error-page="/error/403" />-->
    
            <s:session-management>
                <s:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
            </s:session-management>
        </s:http>
    
        <bean id="loginSuccessHandler" class="uk.police.spsa.security.handler.LoginSuccessHandler"/>
    
        <bean id="loginFailureHandler" class="uk.police.spsa.security.handler.LoginFailureHandler">
            <property name="defaultFailureUrl" value="/login?error=true"/>
        </bean>    
        
        <bean id="accessDeniedHandler" class="uk.police.spsa.security.handler.AccessDeniedHandler">
            <!-- maps to my error controller -->
            <property name="errorPage" value="/error/403"/>
            <!--static jsp -->
            <!--<property name="errorPage" value="/error.jsp"/>-->
    
        </bean>
    </beans>
    It is also worth noting that if i comment out the access-denied-handler completely i do receive the standard 403 error through my browser.

    I also have urlrewrite configured and everything seems to be working fine i believe although i have not ruled out the possibility of this being the problem.

    urlrewite.xml:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    
    <!DOCTYPE urlrewrite
            PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
            "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">
    
    <urlrewrite default-match-type="wildcard">
        <rule>
            <from>/resources/**</from>
            <to>/resources/$1</to>
        </rule>
        <rule>
            <from>/logout</from>
            <to last="true">/logout</to>
        </rule>
        <rule>
            <from>/app_security_check**</from>
            <to last="true">/app_security_check$1</to>
        </rule>
        <rule>
            <from>/error.jsp</from>
            <to last="true">/error.jsp</to>
        </rule>
        <rule>
            <from>/**</from>
            <to>/app/$1</to>
        </rule>
        <outbound-rule>
            <from>/app/**</from>
            <to>/$1</to>
        </outbound-rule>
    </urlrewrite>
    Any help / suggestions would be greatly appreciated.

    Cheers,
    Craig

    SPRING VERSION: 3.0.4.RELEASE
    SPRING SECURITY VERSION: 3.0.5.RELEASE
    GLASSFISH VERSION: 3.0.1

  2. #2
    Join Date
    Jan 2008
    Posts
    1,833

    Default

    Can you post your web.xml? Just to confirm...if you specify the url of error.jsp then it works. However, if you specify a URL of /error/403 it gets a 404. It sounds like the problem is that the request is being forwarded to the URL and UrlRewriteFilter is not mapped to a forward request. Thus it is not rewriting it to /app/error/403. Since it is not rewriting it and there is no mapping to /error/403 it cannot find it. If I were you I would remove the UrlRewriteFilter unless you have good reason to keep it around. Please note you can accomplish pretty restful urls by making your servlet a default servlet (i.e. mapping it to /). See the Spring MVC Showcase for an example of this.

    HTH,
    Rob Winch
    Twitter @rob_winch
    Spring Security Lead
    Spring by Pivotal

  3. #3
    Join Date
    Dec 2010
    Location
    Los Angeles
    Posts
    15

    Default

    Craig,

    You got to define the exceptionTranlationFilet to the your configuration

    Code:
    	<bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    		<property name="authenticationEntryPoint" ref="authenticationEntryPoint" />
    		<property name="accessDeniedHandler" ref="accessDeniedHandler" />
    	</bean>
    
    	<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    		<property name="loginFormUrl" value="/login.jsp" />
    		<property name="forceHttps" value="true" />
    	</bean>
    	
    	<bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
    		<property name="errorPage" value="/accessdenied.html" />
    	</bean>
    
    
    Hope that helps...
    
    Cheers
    Vivek Chutke

  4. #4
    Join Date
    Feb 2009
    Posts
    11

    Default

    Thanks for the replies.

    @rwinch

    To confirm i can access /error.jsp and also /error/403 directly so there is no issue about the mappings or the urlrewrite rules as they work as expected when called on there own. The issue is when i define them as error pages through default handler:

    Code:
    <s:access-denied-handler error-page="/error.jsp" />      
    <s:access-denied-handler error-page="/error/403" />
    or through my custom handler:

    Code:
     
    <s:access-denied-handler ref="accessDeniedHandler"/>
    <bean id="accessDeniedHandler" class="uk.police.spsa.security.handler.AccessDeniedHandler">
            <!-- maps to my error controller -->
            <property name="errorPage" value="/error/403"/>
            <!--static jsp -->
            <!--<property name="errorPage" value="/error.jsp"/>-->
    </bean>
    I'll have a look at the showcase example but the main reason for using the urlrewrite was to allow the pretty urls removing the /app/ for every request and to prevent requests for static resources being sent through the dispatcher servlet.

    I have included my web.xml anyway for reference below.

    @vivekchutke

    That is what I have already except I am using the security namespace to create the same beans as the security namespace appendix describes.

    Security Namespace - Access Denied Handler
    http://static.springsource.org/sprin...denied-handler

    Security Namespace - Form Login (which creates the authenticationEntryPoint)
    http://static.springsource.org/sprin...nsa-form-login

    Security Namespace - Http (which creates the exceptionTranslationFilter)
    http://static.springsource.org/sprin....html#nsa-http

    The problem is that the access-denied-namespace tag causes problems when I try and access protected pages that I do not have the required role for. This causes a 404 not found exeption which i cannot figure out. I have set my log levels for spring to trace but there is no information of any use to try and figure out what the problem is.


    web.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             version="2.5">
    
        <display-name>APP</display-name>
    
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/spring-*.xml
            </param-value>
        </context-param>
    
        <filter>
            <filter-name>springSecurityFilterChain</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>
    
        <filter-mapping>
            <filter-name>springSecurityFilterChain</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <filter>
            <filter-name>UrlRewriteFilter</filter-name>
            <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
        </filter>
    
        <filter-mapping>
            <filter-name>UrlRewriteFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <listener>
            <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher
            </listener-class>
        </listener>
    
        <servlet>
            <servlet-name>spring</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>0</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>spring</servlet-name>
            <url-pattern>/app/*</url-pattern>
        </servlet-mapping>
    
        <servlet>
            <servlet-name>freemarker</servlet-name>
            <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
            <init-param>
                <param-name>TemplatePath</param-name>
                <param-value>/</param-value>
            </init-param>
            <init-param>
                <param-name>NoCache</param-name>
                <param-value>true</param-value>
            </init-param>
            <init-param>
                <param-name>ContentType</param-name>
                <param-value>text/html</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>freemarker</servlet-name>
            <url-pattern>*.ftl</url-pattern>
        </servlet-mapping>
    </web-app>

  5. #5
    Join Date
    Feb 2009
    Posts
    11

    Default

    Thought I would post an update as I found the solution thanks to the pointer from rwinch in the direction of the mvc-showcase.

    The error seemed to be within the urlrewrite filter - not 100% sure exactly what it was although it seems to be around the fact the access denied handler uses dispatcher.forward(...) where the login success handler uses dispatcher.sendRedirect(...).

    My fix has involved be ripping out urlrewrite and using the following configuration:

    In my spring-servlet.xml i added the following line to serve the static resources (the main reason i used urlrewrite in the first place):

    Code:
    <mvc:resources mapping="/resources/**" location="/resources/" />
    In my web.xml I removed the url rewrite filter and altered the url mapping of the Spring DispatcherServlet from

    Code:
    <servlet-mapping>
    	<servlet-name>spring</servlet-name>
    	<url-pattern>/app/*</url-pattern>
    </servlet-mapping>
    to

    Code:
    <servlet-mapping>
    	<servlet-name>spring</servlet-name>
    	<url-pattern>/</url-pattern>
    </servlet-mapping>

    Hope this may help someone as this has tidied up and simplified my code greatly and should also improve performance within the app.

    The mvc:resources tag was new to me and if only I came across this earlier as the definition says it all.

    Configures a handler for serving static resources such as images, js, and, css files with cache headers optimized for efficient loading in a web browser. Allows resources to be served out of any path that is reachable via Spring's Resource handling
    Thanks,
    Craig

  6. #6
    Join Date
    Jan 2008
    Posts
    1,833

    Default

    Thought I would post an update as I found the solution thanks to the pointer from rwinch in the direction of the mvc-showcase.

    The error seemed to be within the urlrewrite filter - not 100% sure exactly what it was although it seems to be around the fact the access denied handler uses dispatcher.forward(...) where the login success handler uses dispatcher.sendRedirect(...).
    Glad you got it figured out. The reason you could access the /error/404 directly was because UrlRewriteFilter was filtering on requests. However, it didn't work with Spring Security because it performs a forward and UrlRewriteFilter wasn't setup to be invoked for forwards. If you want a Filter to be invoked on forwards you need to add something like this:

    Code:
        <filter-mapping>
            <filter-name>UrlRewriteFilter</filter-name>
            <url-pattern>/*</url-pattern>
            <dispatcher>REQUEST</dispatcher>
            <dispatcher>FORWARD</dispatcher>
        </filter-mapping>

    Of course that leads to other problems and that is why I recommended removing the UrlRewriteFilter...often times it is just unnecessary complexity.
    Rob Winch
    Twitter @rob_winch
    Spring Security Lead
    Spring by Pivotal

  7. #7
    Join Date
    Feb 2009
    Posts
    11

    Default

    Yeah i quickly realised that what i was trying to achieve through the urlrewrite filter could be achieved through spring config so didn't hesistate in removing it.

    I had however already looked at the urlrewite rules for the error page but because the type of rule is already of type forward by default it left me stumped.

    Thanks the tip on how to get round this using the dispatcher element of the filter mapping. This is something i have never really altered as i've always just taking the default but it's good to know.

    Cheers,
    Craig

  8. #8

    Default

    I have added Spring Access denied page in follwing way:
    Spring Frame Work: 3.1
    Spring Security: 3.1, Java 1.5+

    Entry in *-security.xml:
    <security:access-denied-handler error-page="/<My Any error page controller name>" />
    Example:
    <security:access-denied-handler error-page="/accessDeniedPage.htm" />
    Error page will always start with "/"

    Entry for controller:

    @Controller
    public class RedirectAccessDenied {

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

    }
    }

    Here 403 is my JSP name.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •