0
votes

I have implemented 'Remember Me' functionality in my Spring MVC application using Spring Security 3.1

My security-context.xml looks like this :

<?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:security="http://www.springframework.org/schema/security"
       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-3.1.xsd">

    <import resource="servlet-context.xml" />
    <security:global-method-security secured-annotations="enabled" />

    <security:http auto-config="true" authentication-manager-ref="am">

    <!-- Restrict URLs based on role -->
    <security:intercept-url pattern="/public/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <security:intercept-url pattern="/resources/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <security:intercept-url pattern="/**" access="ROLE_USER" />

    <!-- Override default login and logout pages -->
    <security:form-login login-page="/public/login" 
                 login-processing-url="/public/loginProcess" 
                 default-target-url="/public/loginSuccess" 
                 authentication-failure-url="/public/login?login_error=1" 
                 always-use-default-target="true" />
    <security:logout logout-url="/public/logout" logout-success-url="/public/login?logout=1" />
    <security:remember-me services-alias="rmService" data-source-ref="dataSource"/>
    <security:custom-filter position="LAST" ref="httpResponseAuthFilter" />
    </security:http>

    <security:authentication-manager id="am">
    <security:authentication-provider >
        <security:password-encoder ref="passwordEncoder" />
        <security:jdbc-user-service data-source-ref="dataSource" />
    </security:authentication-provider>
    </security:authentication-manager>

    <bean id="httpResponseAuthFilter"
    class="mypackage.HttpResponseAuthenticationFilter" >
     <property name="authenticationManager" ref="am"/>
     <property name="rememberMeServices" ref="rmService"></property>
    </bean> 

</beans>

The Filter class is implemented like this :

    public class HttpResponseAuthenticationFilter extends RememberMeAuthenticationFilter {

    @Override
    protected void onSuccessfulAuthentication(final HttpServletRequest request, final HttpServletResponse response,
            final Authentication authResult) {

        super.onSuccessfulAuthentication(request, response, authResult);

        if (authResult != null) {
            // process post authentication logic here..
        }
    }

}

Remember me functionality works fine using the above configuration but while running in eclipse debugger I found that HttpResponseAuthenticationFilter.onSuccessfulAuthentication() doesn't get invoked.

EDIT

After modifying my security-context.xmls and defining the remember-me service using standard Spring beans and referencing the service inside the configuration looks

    <security:http auto-config="true" authentication-manager-ref="am">
    <!-- Restrict URLs based on role -->
    <security:intercept-url pattern="/public/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <security:intercept-url pattern="/resources/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <security:intercept-url pattern="/**" access="ROLE_USER" />

    <!-- Override default login and logout pages -->
    <security:form-login login-page="/public/login" 
                         login-processing-url="/public/loginProcess" 
                         default-target-url="/public/loginSuccess" 
                         authentication-failure-url="/public/login?login_error=1" 
                         always-use-default-target="true" />

    <security:remember-me services-ref="rememberMeService"/>
    <security:logout logout-url="/public/logout" logout-success-url="/public/login?logout=1" />
    <security:custom-filter position="LAST" ref="httpResponseAuthFilter" />
</security:http>

<security:authentication-manager id="am">
    <security:authentication-provider >
        <security:password-encoder ref="passwordEncoder" />
        <security:jdbc-user-service data-source-ref="dataSource" />
    </security:authentication-provider>
    <security:authentication-provider ref="rememberMeAuthenticationProvider" />
</security:authentication-manager>

<bean id="rememberMeAuthenticationProvider" class=
        "org.springframework.security.authentication.RememberMeAuthenticationProvider">
        <property name="key" value="riskAnalysis" /> 
</bean>

<bean id="httpResponseAuthFilter"
    class="mypacakge.HttpResponseAuthenticationFilter" >
     <property name="authenticationManager" ref="am"/>
     <property name="rememberMeServices" ref="rememberMeService"></property>
</bean> 

<bean id="rememberMeService"
    class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
    <property name="userDetailsService" ref="userDetailsService" />
    <property name="key" value="riskAnalysis" />
</bean>

<bean id="userDetailsService"
  class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
    <property name="dataSource" ref="dataSource"/>
</bean>    

Here is what I get in the logs :

*DEBUG: mypackage.HttpResponseAuthenticationFilter - SecurityContextHolder not populated with remember-me token, as it already contained: 'org.springframework.security.authentication.RememberMeAuthenticationToken@303f2184: Principal: org.springframework.security.core.userdetails.User@cb7ea6f6: Username: tarun4; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER'*

So it looks like authentication information is present in the session.

Thanks, Tarun

1

1 Answers

2
votes

The remember-me namespace element already inserts a RememberMeAuthenticationFilter so it will still take precedence over yours, since it comes before it in the filter chain.

If you want to use a custom filter, you should remove the namespace element and use standard Spring beans for the related services. There's an example in the reference manual (Section 11.4.1) which shows the beans needed.