Search code examples
springspring-securityspring-3

spring-security - where can I find the list of ALL security filters registered when I use the <http> element?


There are a default set of filters registered when we use the <http> element in our xml file. This mentions the ordering of filters (whichever we choose to apply), and just above that, it mentions :

<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
  <constructor-arg>
    <list>
      <sec:filter-chain pattern="/restful/**" filters="
           securityContextPersistenceFilterWithASCFalse,
           basicAuthenticationFilter,
           exceptionTranslationFilter,
           filterSecurityInterceptor" />
      <sec:filter-chain pattern="/**" filters="
           securityContextPersistenceFilterWithASCTrue,
           formLoginFilter,
           exceptionTranslationFilter,
           filterSecurityInterceptor" />
    </list>
  </constructor-arg>
</bean>

If the above is the list of default filters, then during debugging, I found that RequestCacheAwareFilter is also called. From where is this filter called and what is its position in the filter chain ? In which condition is AnonymousAuthenticationFilter configured into the chain ?

What's the default filter chain that's configured for me ?

Edit : I have applicationContext.xml and springSecurity.xml. The following is my applicationContext.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:annotation-config />
    <context:spring-configured />

    <!-- Make sure that the part of the file until "End of beans" is identical
         to bean definitions in applicationContext.xml of the main application. -->

    <bean id="adminService" class="org.daud.admin.server.AdminServiceImpl" />
    <bean id="feedbackService" class="org.daud.feedback.server.FeedbackServiceImpl" />
    <bean id="guideService" class="org.daud.guider.server.GuiderServiceImpl" />
    <bean id="messageService" class="org.daud.messages.server.MessageServiceImpl" />
    <bean id="wsService" class="org.daud.guider.server.WSServiceImpl" />

    <bean id="jabxUtil" class="org.daud.common.server.services.JAXBUtil" />
    <bean id="serviceAdvisor" class="org.daud.common.server.ServiceAdvisor" />

    <bean id="userPreferences" class="org.daud.preferences.server.UserPreferencesServiceImpl" />

    <bean id="dynamicClientFactory" class="org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory" factory-method="newInstance" />

    <!-- End of beans. -->

    <!-- For testing. -->

    <bean id="guiderClientService" class="org.daud.guider.server.GuiderClientServiceImpl" />

    <bean id="entityManager" class="com.daud.jpa.DBUtil" factory-method="createEntityManager" lazy-init="true">
        <constructor-arg value="bb-test" />
    </bean>

    <bean id="testUtil" class="com.daud.jpa.JPATestUtil" lazy-init="true">
        <constructor-arg ref="entityManager" />
        <constructor-arg value="org.daud" />
        <constructor-arg value="fixtures" />
    </bean>

</beans>

And this is my springSecurity.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <aop:aspectj-autoproxy proxy-target-class="true" />
    <beans:bean class="com.gwt.ss.GwtExceptionTranslator" />

    <global-method-security secured-annotations="enabled" access-decision-manager-ref="methodSecurityAccessDecisionManager"/>
    <http use-expressions="true" auto-config="false" disable-url-rewriting="true" access-decision-manager-ref="urlSecurityAccessDecisionManager"> 
        <intercept-url pattern="/favicon.ico" filters="none" />
        <intercept-url pattern="/login.jsp" filters="none" />

        <!-- Allow access only to admins and superadmins for the following 2 url patterns -->
        <intercept-url pattern="/do/admin/*" access="hasAdminStatus(3,4)" />
        <intercept-url pattern="/admin/*" access="hasAdminStatus(3,4)" />

        <intercept-url pattern="/**/*.html" access="isAuthenticated()" /> <!-- access="isAuthenticated()"-->
        <intercept-url pattern="/do/**" access="isAuthenticated()" />
        <intercept-url pattern="/**" access="isAuthenticated()" />
        <custom-filter after="FILTER_SECURITY_INTERCEPTOR" ref="switchUserProcessingFilter"/>

        <form-login login-page="/login" login-processing-url="/do/login" authentication-failure-url="/login?authfailed=true" authentication-success-handler-ref="myAuthenticationSuccessHandler"/>

        <!-- Using success-handler-ref instead of logout-success-url for asynchronous logout. -->
        <logout invalidate-session="true" success-handler-ref="logoutSuccessHandler" logout-url="/do/logout" />
    </http>

    <beans:bean id="urlSecurityAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
        <beans:property name="decisionVoters">
            <beans:list>
                <beans:bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
                    <beans:property name="expressionHandler" ref="myWebSecurityExpressionHandler"/>
                </beans:bean>
            </beans:list>
        </beans:property>
    </beans:bean>
    <beans:bean id="myWebSecurityExpressionHandler" class="org.daud.common.server.security.MyWebSecurityExpressionHandler"/>
    <beans:bean id="myWebSecurityExpressionRoot" class="org.daud.common.server.security.MyWebSecurityExpressionRoot" scope="prototype"/>
    <!-- For asynchronous login -->

    <beans:bean id="methodSecurityAccessDecisionManager"
        class="org.springframework.security.access.vote.AffirmativeBased">
        <beans:property name="decisionVoters">
            <beans:list>
                <beans:bean class="org.springframework.security.access.vote.RoleVoter" p:rolePrefix="" />
                <beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
                <beans:bean class="org.daud.common.server.security.AllowPrivilegedRolesVoter">
                    <beans:property name="privilegedRoleTypes">
                        <beans:set>
                            <beans:value>ROOT</beans:value>
                        </beans:set>
                    </beans:property>
                </beans:bean>
            </beans:list>
        </beans:property>
    </beans:bean>

    <beans:bean class="com.gwt.ss.GwtUsernamePasswordAuthority">
        <beans:property name="authenticationManager" ref="authenticationManager" />
    </beans:bean>
    <beans:bean id="myAuthenticationSuccessHandler" class="org.daud.common.server.security.myAuthenticationSuccessHandler">
        <!-- If redirection after logging in is to URLs containing these strings, the redirection will instead be to '/' -->
        <beans:property name="partialURLsRequiringRedirection">
            <beans:list>
                <beans:value>/do/</beans:value>
                <beans:value>/exitUser</beans:value>
            </beans:list>
        </beans:property>
    </beans:bean>
    <beans:bean id="userSwitchSuccessHandler" class="org.daud.common.server.security.myUserSwitchSuccessHandler"/>
    <beans:bean id="userServices" class="org.daud.common.server.security.myUserServices"/>

    <beans:bean id="switchUserProcessingFilter" class="org.springframework.security.web.authentication.switchuser.SwitchUserFilter">
        <beans:property name="userDetailsService" ref="userServices" />
        <beans:property name="switchUserUrl" value="/admin/switchUser" />
        <beans:property name="exitUserUrl" value="/admin/exitUser" />
        <beans:property name="successHandler" ref="userSwitchSuccessHandler"></beans:property>
    </beans:bean>

    <!-- For asynchronous logout -->

    <beans:bean id="logoutSuccessHandler" class="com.gwt.ss.GwtLogoutSuccessHandler" p:logoutSuccessUrl="/login" />

    <beans:bean id="myAuthenticationProvider" class="org.daud.common.server.security.myAuthenticationProvider" />
    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="myAuthenticationProvider" />
    </authentication-manager>

</beans:beans>

Solution

  • If you turn on debug logging for org.springframework.security.web.FilterChainProxy you will see, for each request, every filter that it passes through.

    For example (I am also using Spring Security OAuth).

    11:18:39.123 FilterChainProxy - /user/login at position 1 of 17 in additional filter chain; firing Filter: 'BasicUserApprovalFilter'
    11:18:39.123 FilterChainProxy - /user/login at position 2 of 17 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
    11:18:39.124 FilterChainProxy - /user/login at position 3 of 17 in additional filter chain; firing Filter: 'LogoutFilter'
    11:18:39.124 FilterChainProxy - /user/login at position 4 of 17 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
    11:18:39.124 FilterChainProxy - /user/login at position 5 of 17 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
    11:18:39.124 FilterChainProxy - /user/login at position 6 of 17 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
    11:18:39.124 FilterChainProxy - /user/login at position 7 of 17 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
    11:18:39.124 FilterChainProxy - /user/login at position 8 of 17 in additional filter chain; firing Filter: 'RememberMeAuthenticationFilter'
    11:18:39.125 FilterChainProxy - /user/login at position 9 of 17 in additional filter chain; firing Filter: 'ForgotPasswordAuthenticationFilter'
    11:18:39.125 FilterChainProxy - /user/login at position 10 of 17 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
    11:18:39.125 FilterChainProxy - /user/login at position 11 of 17 in additional filter chain; firing Filter: 'SessionManagementFilter'
    11:18:39.125 FilterChainProxy - /user/login at position 12 of 17 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
    11:18:39.125 FilterChainProxy - /user/login at position 13 of 17 in additional filter chain; firing Filter: 'OAuth2ExceptionHandlerFilter'
    11:18:39.125 FilterChainProxy - /user/login at position 14 of 17 in additional filter chain; firing Filter: 'VerificationCodeFilter'
    11:18:39.125 FilterChainProxy - /user/login at position 15 of 17 in additional filter chain; firing Filter: 'OAuth2AuthorizationFilter'
    11:18:39.125 FilterChainProxy - /user/login at position 16 of 17 in additional filter chain; firing Filter: 'OAuth2ProtectedResourceFilter'
    11:18:39.125 FilterChainProxy - /user/login at position 17 of 17 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
    

    If you want to get the filters programmatically you can inject the FilterChainProxy and get the filterChainMap's values.

    For example:

    @Autowired var filterChainProxy: FilterChainProxy = _
    //...
    val filterChains = filterChainProxy.getFilterChainMap.values
    

    If you only want to see the filters that <http> adds then you should look at the source for HttpSecurityBeanDefinitionParser.