Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring FilterChainProxy with filterSecurityInterceptor not working correctly?

I have a spring application with the config files as shown below. All configs seem correct but while debugging I found that, during the initialization spring creates two beans for FilterSecurityInterceptor one without any intercept-url rules and the other with the rules that I have specified. When a request comes, it uses the FilterSecurityInterceptor bean with no intercept-url rules. So I see the following log:

DEBUG FilterSecurityInterceptor:183 - Public object - authentication not attempted

But the request URL falls under the intercept URL rule. I debugged and found that this is because the bean used didn't have any intercept rules in httpMethodMap of DefaultFilterInvocationSecurityMetadataSource. I am not sure what is wrong here.

Below is the applicationContext-security.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="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.2.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"
    default-init-method="init">

    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider
            user-service-ref="userDetailService">
        </security:authentication-provider>
    </security:authentication-manager>

    <alias name="filterChainProxy" alias="springSecurityFilterChain" />

    <bean id="accessDecisionManager"
        class="org.springframework.security.access.vote.AffirmativeBased">
        <property name="decisionVoters">
            <list>
                <bean class="org.springframework.security.access.vote.RoleVoter" />
                <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
            </list>
        </property>
    </bean>

    <bean id="consoleAuthenticationSuccessHandler"
        class="custom_class">
        <property name="defaultTargetUrl" value="/loginSuccess.htm" />
        <property name="targetUrlParameter" value="targetURL" />
    </bean>

    <bean id="consoleAuthenticationFailureHandler"
        class="custom_class">
        <property name="loginFailureUrl" value="/loginFailure.htm" />
    </bean>

    <bean id="consoleLogoutSuccessHandler"
        class="custom_class">
        <property name="logoutUrl" value="/loggedout.htm" />
    </bean>

    <bean id="userDetailService"
        class="custom_class">
    </bean>

    <security:http auto-config="true"
        security-context-repository-ref="securityContextRepository">
        <security:form-login authentication-failure-url="/loginFailure.htm"
            default-target-url="/loginSuccess.htm"
            authentication-success-handler-ref="consoleAuthenticationSuccessHandler" />
        <security:logout success-handler-ref="consoleLogoutSuccessHandler" />
        <security:anonymous enabled="false" />
        <security:session-management
            session-fixation-protection="none" />
    </security:http>

    <bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
        <security:filter-chain-map path-type="ant">
            <security:filter-chain pattern="/login.htm*"
                filters="none" />
            <security:filter-chain pattern="/**"
                filters="securityContextFilter, logoutFilter, formLoginFilter, servletApiFilter, exceptionTranslator, filterSecurityInterceptor" />
        </security:filter-chain-map>
    </bean>

    <bean id="securityContextRepository"
        class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />

    <bean id="securityContextFilter"
        class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
        <property name="securityContextRepository" ref="securityContextRepository" />
    </bean>
    <bean id="logoutFilter"
        class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <constructor-arg ref="consoleLogoutSuccessHandler"
            index="0"
            type="org.springframework.security.web.authentication.logout.LogoutSuccessHandler" />
        <constructor-arg>
            <list>
                <bean
                    class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
            </list>
        </constructor-arg>
    </bean>

    <bean id="servletApiFilter"
        class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter" />

    <bean id="exceptionTranslator"
        class="org.springframework.security.web.access.ExceptionTranslationFilter">
        <property name="authenticationEntryPoint">
            <bean
                class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
                <property name="loginFormUrl" value="/login.jsp" />
            </bean>
        </property>
    </bean>

    <bean id="formLoginFilter"
        class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="authenticationSuccessHandler" ref="consoleAuthenticationSuccessHandler" />
        <property name="authenticationFailureHandler" ref="consoleAuthenticationFailureHandler" />
    </bean>

    <bean id="filterSecurityInterceptor"
        class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
        <property name="securityMetadataSource">
            <security:filter-security-metadata-source>
                <security:intercept-url pattern="/login.htm*"
                    access="ROLE_ANONYMOUS" />
                <security:intercept-url pattern="/**"
                    access="ROLE_USER,ROLE_ADMIN" />
            </security:filter-security-metadata-source>
        </property>
        <property name="accessDecisionManager" ref="accessDecisionManager" />
        <property name="authenticationManager" ref="authenticationManager" />
    </bean>

</beans>

Appreciate any help here.

like image 452
vivek_jonam Avatar asked Jun 04 '16 05:06

vivek_jonam


People also ask

How does a Spring Security filter chain work?

Spring Security maintains a filter chain internally where each of the filters has a particular responsibility and filters are added or removed from the configuration depending on which services are required. The ordering of the filters is important as there are dependencies between them.

Is WebSecurityConfigurerAdapter deprecated?

From Spring Boot 2.7, WebSecurityConfigurerAdapter is deprecated. In this tutorial, I will show you how to update your Web Security Config class in Spring Security without the WebSecurityConfigurerAdapter example.

How should passwords be stored in spring?

Instead of using just the password as input to the hash function, random bytes (known as salt) would be generated for every users' password. The salt and the user's password would be ran through the hash function which produced a unique hash. The salt would be stored alongside the user's password in clear text.

What is FilterSecurityInterceptor?

Class FilterSecurityInterceptorPerforms security handling of HTTP resources via a filter implementation. The SecurityMetadataSource required by this security interceptor is of type FilterInvocationSecurityMetadataSource . Refer to AbstractSecurityInterceptor for details on the workflow.


1 Answers

You have <security:http> element in the config. From the documentation:

38.1.2 <http>
Each <http> namespace block always creates an SecurityContextPersistenceFilter, an ExceptionTranslationFilter and a FilterSecurityInterceptor. These are fixed and cannot be replaced with alternatives.

So your <bean id="filterSecurityInterceptor"> is ignored. Instead of

<bean id="filterSecurityInterceptor"
    class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <property name="securityMetadataSource">
        <security:filter-security-metadata-source>
            <security:intercept-url pattern="/login.htm*"
                access="ROLE_ANONYMOUS" />
            <security:intercept-url pattern="/**"
                access="ROLE_USER,ROLE_ADMIN" />
        </security:filter-security-metadata-source>
    </property>
    <property name="accessDecisionManager" ref="accessDecisionManager" />
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

you should change <security:http> to include something like

<security:http ...
        authentication-manager-ref="authenticationManager">
    ...
    <security:intercept-url pattern="/login.htm*"
        access="ROLE_ANONYMOUS" />
    <security:intercept-url pattern="/**"
        access="ROLE_USER,ROLE_ADMIN" />
</security:http>

You don't need <bean id="accessDecisionManager">, because (quote from the docs) "by default an AffirmativeBased implementation is used for with a RoleVoter and an AuthenticatedVoter", which is exactly what you define.

Also your <bean id="securityContextFilter"> is ignored, instead you should add security-context-repository-ref="securityContextRepository" attribute to http element.
And your <bean id="exceptionTranslator"> is ignored, I'm not sure how to replace it properly.

And you manually define a lot of org.springframework.security beans. I suspect that most of them are either unnecessary (defined by default), or should be defined using specialized elements of security: namespace, instead of raw spring beans.

like image 151
Roman Avatar answered Oct 17 '22 23:10

Roman