Announcement Announcement Module
Collapse
No announcement yet.
SecurityContextHolderAwareRequestFilter/Wrapper improvements Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • SecurityContextHolderAwareRequestFilter/Wrapper improvements

    I had to rewrite these classes in order to meet two requirements, and I want to know if these are of general interest:
    • Add a property 'rolePrefix' to SecurityContextHolderAwareRequestFilter. This is passed on to the SecurityContextHolderAwareRequestWrapper. The prefix, if set, is prepended to the role name before comparison in the isUserInRole method. For example, if set to 'ROLE_', It allows you to write
      Code:
      request.isUserInRole("Admin")
      insted of
      Code:
      request.isUserInRole("ROLE_Admin")
    • We use the <error-page> mechanism to display errors in the web application. At least in Tomcat, and when Acegi is configured to use a <url-pattern> for the filter mapping, the Acegi filters bypassed when the error page is rendered. If you use the HttpSessionContextIntegrationFilter in your filter chain, the SecurityContext is gone when you render the error page.

      I solved this problem by putting the SecurityContext as an attribute of the HttpServletRequest. This is done in the SecurityContextHolderAwareRequestFilter when it wraps the request (although this could perhaps be refactored out into a separate filter). When the wrapper tries to find the Authetication object, and none is found in the SecurityContextHolder, it tries the request attribute to see if it is there before giving up and returning null.

    Comments?

  • #2
    Originally posted by Rolf Arne Corneliussen
    I had to rewrite these classes in order to meet two requirements, and I want to know if these are of general interest:
    • We use the <error-page> mechanism to display errors in the web application. At least in Tomcat, and when Acegi is configured to use a <url-pattern> for the filter mapping, the Acegi filters bypassed when the error page is rendered. If you use the HttpSessionContextIntegrationFilter in your filter chain, the SecurityContext is gone when you render the error page.

      I solved this problem by putting the SecurityContext as an attribute of the HttpServletRequest. This is done in the SecurityContextHolderAwareRequestFilter when it wraps the request (although this could perhaps be refactored out into a separate filter). When the wrapper tries to find the Authetication object, and none is found in the SecurityContextHolder, it tries the request attribute to see if it is there before giving up and returning null.
    When using servlet specification 2.4, this can probably be solved by specifying a filter chain with a HttpSessionContextIntegrationFilter and a SecurityContextHolderAwareRequestFilter to handle the error page resources. To ensure this happens, use a <dispatcher>ERROR</dispatcher> element inside the <filter-mapping> element.

    Anyway, is there something unsecure or 'wrong' with storing the security context as an attribute in the HttpServletrequest?

    Comment


    • #3
      I can't see any problem with storing it in the HttpServletRequest for use by error pages and alike.

      Comment


      • #4
        Rolf, I am interested in knowing more about the classes involved in this...would it be convenient for you to email me the classes, web.xml, and applicationContext-whatever.xml?

        Would greatly appreciate it.

        -Ro

        Comment


        • #5
          Originally posted by rpaul
          Rolf, I am interested in knowing more about the classes involved in this...would it be convenient for you to email me the classes, web.xml, and applicationContext-whatever.xml?

          Would greatly appreciate it.

          -Ro
          I'm sorry I cannot do that for different reasons. However, I can create JIRA issues for the two points mentioned here:

          * Add a 'rolePrefix' property to the SecurityContextHolderAwareRequestFilter

          * Ensure the existence of a SecurityContext when rendering error pages.

          Comment


          • #6
            Dispatcher

            Hi

            I tried the dispatcher suggestion from above and it work great on my error page.
            Unfortunetly now it dosen't work on my other normal pages.
            Code:
            <filter-mapping>
            		<filter-name>Acegi Filter Chain Proxy</filter-name>
            		<url-pattern>/*</url-pattern>
            	
            <!--		<dispatcher>FORWARD</dispatcher>-->
            <!--		<dispatcher>INCLUDE</dispatcher>-->
            <!--		<dispatcher>ERROR</dispatcher>-->
            		<dispatcher>REQUEST</dispatcher>
            	</filter-mapping>
            With request on, it works on normal pages.
            with error on and the other two without request it works on error pages.
            with all on it works on normal pages but not error pages.

            Any ideas?

            Comment


            • #7
              Originally posted by warer
              Hi

              I tried the dispatcher suggestion from above and it work great on my error page.
              Unfortunetly now it dosen't work on my other normal pages.
              Code:
              <filter-mapping>
              		<filter-name>Acegi Filter Chain Proxy</filter-name>
              		<url-pattern>/*</url-pattern>
              	
              <!--		<dispatcher>FORWARD</dispatcher>-->
              <!--		<dispatcher>INCLUDE</dispatcher>-->
              <!--		<dispatcher>ERROR</dispatcher>-->
              		<dispatcher>REQUEST</dispatcher>
              	</filter-mapping>
              With request on, it works on normal pages.
              with error on and the other two without request it works on error pages.
              with all on it works on normal pages but not error pages.

              Any ideas?
              According to the servlet specification, a single dispatcher element with value REQUEST is equivalent to having none, so the correct configuration is

              Code:
              <dispatcher>ERROR</dispatcher>
              <dispatcher>REQUEST</dispatcher>
              I believe the reason it does not work is that the HttpSessionContextIntegrationFilter is not designed to work with error pages, because it is designed to be applied only one per request. I have not got around to file a Jira issue for this yet, but I will.

              Lets take the simple example that you have set up an error page config for handling authrorization failures, like

              Code:
              <error-page>
                 <error-code>403</error-code>
                 <location>/unauthorized.jsp</location>
              </error-page>
              If a user lacks a required role, ExceptionTranslationFilter by default issues a sendError on the response. When the request processing returns up the filter chain, it eventually reaches the HttpSessionContextIntegrationFilter and it executes

              Code:
              // Remove SecurityContextHolder contents
              SecurityContextHolder.clearContext();
              When the container finds out that it should generate an error page, it is filtered though acegi (because of the <dispatcher>ERROR</dispatcher> element). When the HttpSessionContextIntegrationFilter is invoked for the second time on the same request, it just passes control down the filter chain without setting the proper security context. The code snippet below from HttpSessionContextIntegrationFilter explains the behaviour
              Code:
              if ((request != null) && (request.getAttribute(FILTER_APPLIED) != null)) {
                 // ensure that filter is only applied once per request
                 chain.doFilter(request, response);
              } else {
                 if (request != null) {
                    request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
                 }
                 <normal processing of session context integration>
              I would suggest that the attribute is set to null when the context is cleared, like

              Code:
              // Remove SecurityContextHolder contents
              SecurityContextHolder.clearContext();
              request.setAttribute(FILTER_APPLIED, null);
              But I really do not know the ramifications of this, and the Acegi team may know a better solution.


              A safe workaournd would be to write a simple filter

              Code:
              public class RemoveFilterAppliedFilter implements Filter {
              
                 public void init( FilterConfig filterConfig ) throws ServletException {}
              
                 public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain ) throws IOException, ServletException {
                    servletRequest.setAttribute( "__acegi_session_integration_filter_applied", null );
                    filterChain.doFilter( servletRequest, servletResponse );
                 }
              
                 public void destroy() {}
              
              }
              Then in web.xml, set up the filter
              Code:
              <filter>
                 <filter-name>ErrorPageFilter</filter-name>
                 <filter-class>RemoveFilterAppliedFilter</filter-class>
              </filter>
              and place if BEFORE acegi filter (also in web.xml)

              Code:
              <filter-mapping>
                 <filter-name>ErrorPageFilter</filter-name>
                 <url-pattern>/*</url-pattern>
                 <dispatcher>ERROR</dispatcher>
              </filter-mapping>
              
              <filter-mapping>
                 <filter-name>AcegiFilterChainProxy</filter-name>
                 <url-pattern>/*</url-pattern>
                 <dispatcher>REQUEST</dispatcher>
                 <dispatcher>ERROR</dispatcher>
              </filter-mapping>

              Cheers,

              Rolf Arne

              Comment


              • #8
                I've finally filed the Jira issues. SEC-302 and SEC-305.

                Comment


                • #9
                  Thanks for the workaround, it works.
                  Hope they fix this in 1.1 release.

                  Comment

                  Working...
                  X