How to implement two different spring security authentication from same login form - spring

I have a requirement that on the login page I have a userId , password field and also another text entry field called customer. If a user logins in with userId and password , the spring-security configuration which I have works good.
Second login scenario is If the customer puts in only their customer Id , they are supposed to login to a different page as well. How do I make the two different logins works with the same spring-security xml configuration from the same login page.
<security:http auto-config="true" use-expressions="true" >
<!-- URL restrictions (order is important!) Most specific matches should be at top -->
<!-- Don't set any role restrictions on login.jsp. Any requests for the login page should be available for anonymous users -->
<security:intercept-url pattern="/login.jsp*" access="isAuthenticated()" />
<security:access-denied-handler error-page="/noaccess.jsp" />
<security:intercept-url pattern="/board.htm" access="hasRole('ROLE_ALL_USER')" />
<security:intercept-url pattern="/AddItems.htm*" access="hasRole('ROLE_USER')" />
<!-- Set the login page and what to do if login fails -->
<security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" />
<!-- Set the logout page and where to go after logout is successful -->
<security:logout logout-url="/logout" logout-success-url="/logoutSuccess.jsp" />
<security:custom-filter position="PRE_AUTH_FILTER" ref="customPreAuthFilter" />
<security:custom-filter ref="switchUserFilter" position="SWITCH_USER_FILTER" />
</security:http>
<security:http>
</security:http>
<beans:bean id="customPreAuthFilter" class="org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="preauthAuthProvider" />
</security:authentication-manager>
<!-- Load the UserDetails object for the user. -->
<beans:bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService">
<beans:bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<beans:property name="userDetailsService" ref="currentUserDetailsService"/>
</beans:bean>
</beans:property>
</beans:bean>
<!-- Aliasing (Switch User) -->
<beans:bean id="switchUserFilter" class="org.springframework.security.web.authentication.switchuser.SwitchUserFilter">
<beans:property name="userDetailsService" ref="currentUserDetailsService" />
</beans:bean>
Thanks
Dhiren
#Ritesh Thanks for the link.. I tried your solution but My Filter does not get invoked.
does web.xml need to be modified.
Any way I tried to implement the entire springSecurityFilterChain but still I have not able to invoke my Filter from my login form. My filter that I need invoked is customBadgeAuthFilter
<beans:bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<beans:constructor-arg>
<beans:list>
<security:filter-chain pattern="/resources/**" filters="none"/>
<security:filter-chain pattern="/**"
filters="securityContextPersistenceFilterWithASCTrue,
logoutFilter,
customBadgeAuthFilter,
formLoginFilter,
formLoginExceptionTranslationFilter,
filterSecurityInterceptor" />
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="securityContextPersistenceFilterWithASCTrue"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<beans:constructor-arg>
<beans:bean class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="formLoginExceptionTranslationFilter"
class="org.springframework.security.web.access.ExceptionTranslationFilter">
<beans:constructor-arg>
<beans:bean
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:constructor-arg value="/login"/>
</beans:bean>
</beans:constructor-arg>
<beans:property name="accessDeniedHandler">
<beans:bean
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<beans:property name="errorPage" value="/exception" />
</beans:bean>
</beans:property>
</beans:bean>
<beans:bean id="formLoginFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="allowSessionCreation" value="true"/>
<beans:property name="authenticationSuccessHandler">
<beans:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<beans:constructor-arg value="/"/>
<beans:property name="alwaysUseDefaultTargetUrl" value="true"/>
</beans:bean>
</beans:property>
<beans:property name="authenticationFailureHandler">
<beans:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:constructor-arg value="/login?error=true"/>
</beans:bean>
</beans:property>
</beans:bean>
<beans:bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="accessDecisionManager" ref="accessDecisionManager" />
<beans:property name="runAsManager" ref="runAsManager" />
<beans:property name="securityMetadataSource">
<security:filter-security-metadata-source use-expressions="true">
<security:intercept-url pattern="/**"
access="isAuthenticated()" />
</security:filter-security-metadata-source>
</beans:property>
</beans:bean>
<beans:bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.access.vote.RoleVoter"/>
<beans:bean class="org.springframework.security.web.access.expression.WebExpressionVoter"/>
</beans:list>
</beans:constructor-arg>
<beans:property name="allowIfAllAbstainDecisions" value="false"/>
</beans:bean>
<beans:bean id="runAsManager"
class="org.springframework.security.access.intercept.RunAsManagerImpl">
<beans:property name="key" value="TELCO_RUN_AS"/>
</beans:bean>
<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg value="/login"/>
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler">
<beans:constructor-arg>
<beans:list>
<beans:value>JSESSIONID</beans:value>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="customBadgeAuthFilter" class="com.company.security.filter.BadgeProcessingSecurityFilter">
<beans:constructor-arg value="/login.jsp"></beans:constructor-arg>
<beans:property name="authenticationManager" ref="authManager" />
</beans:bean>
<security:authentication-manager alias="authManager" >
<security:authentication-provider ref='normalAuthenticationProvider ' />
<security:authentication-provider ref='badgeAuthenticationProvider ' />
<security:authentication-provider ref="preauthAuthProvider" />
</security:authentication-manager>
<beans:bean id="loginUrlAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.jsp"/>
</beans:bean>
<beans:bean id="badgeAuthenticationProvider" class="com.company.security.filter.BadgeAuthenticationProvider">
</beans:bean>
I think I finally figured how to get my securityFilter to get invoked.
I was doing debugging to see the springsecurity flow and see that there is a method called. requestAuthorization in the subclass of AbstractAuthenticationProcessingFilter. It compares the uri which is configured for the default value for the filter to get invoked and if they don't match the filter is bypassed. For some reason even thought the POSt request is /j_security_check .. it transforms into FSS/home.htm when it is being compared and so the filter was getting bypassed.

Related

Spring Security CAS and HttpBasic, CasAuthentcationProvider not invoked after ticket granted

I have a maven multi-modules application where the main module depends on others. This main module is secured with Spring Security CAS and submodules required a basic authentication. This is a example of the security configuration of a submodule:
<security:http name="boobkingapiHttp" create-session="stateless" pattern="/hub/book/**"
authentication-manager-ref="apiAuthenticationManager">
<security:intercept-url pattern="/hub/book" access="ROLE_ORDER_MANAGER" />
<security:http-basic />
</security:http>
And the security configuration for the main module:
<security:http entry-point-ref="casEntryPoint" pattern="/**" realm="ecab" use-expressions="false">
<security:intercept-url pattern="/flow/googlestatistics/**" access="ROLE_ADMIN" />
<security:intercept-url pattern="/**" access="ROLE_ADMIN" />
<security:custom-filter position="CAS_FILTER" ref="casFilter" />
<security:logout logout-success-url="/logout.xhtml"/>
<security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
<security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
</security:http>
<beans:bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="casEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<beans:property name="loginUrl" value="http://localhost:8082/sso/login" />
<beans:property name="serviceProperties" ref="serviceProperties" />
</beans:bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="casAuthenticationProvider" />
</security:authentication-manager>
<beans:bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="authenticationUserDetailsService">
<beans:bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<beans:constructor-arg ref="hwsAuthenticationUserDetailsService" />
</beans:bean>
</beans:property>
<beans:property name="serviceProperties" ref="serviceProperties" />
<beans:property name="ticketValidator">
<beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<beans:constructor-arg index="0" value="http://localhost:8082/sso" />
</beans:bean>
</beans:property>
<beans:property name="key" value="an_id_for_this_auth_provider_only" />
</beans:bean>
<beans:bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<beans:property name="service" value="http://localhost:8080/cas-client/login/cas" />
<beans:property name="sendRenew" value="false" />
</beans:bean>
The problem is, when the CAS server grants the ticket and redirects to the service url: http://localhost:8080/cas-client/login/cas?ticket=ST-19-1clKw2tZ5MVp0OznfAun the casAuthenticationProvider is not invoked. The one invoked is the submodule's authenticationProvider and the result is 401 Unauthorized error.
Why the CAS SecurityFilterChain is not invoked? I thought that was handled by Spring Security CAS but it seems not.
I use Spring Security 5.1.2.RELEASE
Thanks a lot for your help.
I found the reason why the CasAuthenticationProvider was not invoked. It's just because of this:
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="casAuthenticationProvider" />
</security:authentication-manager>
I changed alias to id.

Spring Security Remember-me with Ajax login

I have implemented spring security ajax login. .
I defined my own customAuthenticationEntryPoint, authenticationFilter, securityLoginSuccessHandler. It can successfully authenticate the user. However, when I add the remember me part. It does not work. There is no SQL run in the database to insert token into persistent_logins. I do not know if there is anything wrong with my configuration? Please help.
<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:util="http://www.springframework.org/schema/util"
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.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<http pattern="/resources/**" security="none" />
<http auto-config="false" use-expressions="true" entry-point-ref="customAuthenticationEntryPoint">
<intercept-url pattern="/**" access="permitAll" />
<access-denied-handler error-page="/denied" />
<logout invalidate-session="true" delete-cookies="JSESSIONID"
success-handler-ref="securityLogoutSuccessHandler" logout-url="/logout" />
<custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER" />
<csrf />
<!-- enable remember me -->
<remember-me
services-ref = "rememberMeServices"
key = "_spring_security_remember_me" />
</http>
<beans:bean id="rememberMeServices"
class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
<beans:property name="key" value="_spring_security_remember_me"/>
<beans:property name="alwaysRemember" value="true"/>
<beans:property name="tokenRepository" ref="jdbcTokenRepository"/>
<beans:property name="userDetailsService" ref="userDetailsService"/>
</beans:bean>
<beans:bean id="jdbcTokenRepository"
class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
<beans:property name="createTableOnStartup" value="false"/>
<beans:property name="dataSource" ref="dataSource"/>
</beans:bean>
<beans:bean id="customAuthenticationEntryPoint"
class="com.tong.beau.service.security.CustomAuthenticationEntryPoint">
<beans:property name="loginPageUrl" value="/login" />
<beans:property name="returnParameterEnabled" value="true" />
<beans:property name="returnParameterName" value="r" />
</beans:bean>
<beans:bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="filterProcessesUrl" value="/security_check" /><!--
change here if customize form action -->
<!-- handler are for login with ajax POST -->
<beans:property name="authenticationFailureHandler"
ref="securityLoginFailureHandler" />
<beans:property name="authenticationSuccessHandler"
ref="securityLoginSuccessHandler" />
<beans:property name="PasswordParameter" value="password" /><!--
change here for password field name in the form -->
<beans:property name="UsernameParameter" value="username" /><!--
change here for username field name in the form -->
</beans:bean>
<beans:bean id="securityLoginSuccessHandler"
class="com.tong.beau.service.security.SecurityLoginSuccessHandler">
<beans:property name="defaultTargetUrl" value="/" />
<beans:property name="targetUrlParameter" value="return-url"/>
</beans:bean>
<beans:bean id="securityLoginFailureHandler"
class="com.tong.beau.service.security.SecurityLoginFailureHandler">
<beans:property name="defaultFailureUrl" value="/login/failure" />
</beans:bean>
<beans:bean id="securityLogoutSuccessHandler"
class="com.tong.beau.service.security.SecurityLogoutSuccessHandler">
</beans:bean>
<beans:bean id="encoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userDetailsService">
<password-encoder ref="encoder" />
</authentication-provider>
</authentication-manager>
</beans:beans>
Since I implemented my CustomAuthenticationEntryPoint, do I need to handle the remember me service in the entry point?
After looking at the source code of Spring Security 4.0.3, I found out that the default parameter is actually defined as this:
public static final String DEFAULT_PARAMETER = "remember-me";
So what I did was to edit the front end to send the data with name "remember-me".
Before Spring Security 4.0.3, the default parameter was _spring_security_remember_me
That would be worth of mention. The configuration also has some problems.
My working configuration is as following.
<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:util="http://www.springframework.org/schema/util"
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/util
http://www.springframework.org/schema/util/spring-util.xsd">
<http pattern="/resources/**" security="none" />
<http auto-config="false" use-expressions="true" entry-point-ref="customAuthenticationEntryPoint">
<intercept-url pattern="/**" access="permitAll" />
<access-denied-handler error-page="/denied" />
<logout invalidate-session="true" delete-cookies="JSESSIONID"
success-handler-ref="securityLogoutSuccessHandler" logout-url="/logout" />
<custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER" />
<custom-filter ref="rememberMeFilter" after="FORM_LOGIN_FILTER" />
<csrf />
<remember-me key = "remember-me" services-ref="rememberMeServices"/>
</http>
<beans:bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<beans:constructor-arg ref="authenticationManager"/>
<beans:constructor-arg ref="rememberMeServices"/>
</beans:bean>
<beans:bean id="rememberMeServices"
class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
<beans:constructor-arg value="remember-me"/>
<beans:constructor-arg ref="userDetailsService"/>
<beans:constructor-arg ref="jdbcTokenRepository"/>
</beans:bean>
<beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<beans:constructor-arg value="remember-me"/>
</beans:bean>
<beans:bean id="jdbcTokenRepository"
class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
<beans:property name="createTableOnStartup" value="false"/>
<beans:property name="dataSource" ref="dataSource"/>
</beans:bean>
<beans:bean id="customAuthenticationEntryPoint"
class="com.tong.beau.service.security.CustomAuthenticationEntryPoint">
<beans:property name="loginPageUrl" value="/login" />
<beans:property name="returnParameterEnabled" value="true" />
<beans:property name="returnParameterName" value="r" />
</beans:bean>
<beans:bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="rememberMeServices" ref="rememberMeServices" />
<beans:property name="filterProcessesUrl" value="/security_check" />
<!-- change here if customize form action -->
<!-- handler are for login with ajax POST -->
<beans:property name="authenticationFailureHandler"
ref="securityLoginFailureHandler" />
<beans:property name="authenticationSuccessHandler"
ref="securityLoginSuccessHandler" />
<beans:property name="PasswordParameter" value="password" />
<!-- change here for password field name in the form -->
<beans:property name="UsernameParameter" value="username" />
<!-- change here for username field name in the form -->
</beans:bean>
<beans:bean id="securityLoginSuccessHandler"
class="com.tong.beau.service.security.SecurityLoginSuccessHandler">
<beans:property name="defaultTargetUrl" value="/" />
<beans:property name="targetUrlParameter" value="return-url"/>
</beans:bean>
<beans:bean id="securityLoginFailureHandler"
class="com.tong.beau.service.security.SecurityLoginFailureHandler">
<beans:property name="defaultFailureUrl" value="/login/failure" />
</beans:bean>
<beans:bean id="securityLogoutSuccessHandler"
class="com.tong.beau.service.security.SecurityLogoutSuccessHandler">
</beans:bean>
<beans:bean id="encoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<authentication-manager alias="authenticationManager">
<authentication-provider ref="rememberMeAuthenticationProvider">
</authentication-provider>
<authentication-provider user-service-ref="userDetailsService">
<password-encoder ref="encoder" />
</authentication-provider>
</authentication-manager>
</beans:beans>

Spring security SessionRegistry and bean based configuration woes

I'm using Spring Security 3.0.5 and trying to get a count of currently logged in users. My scenario is Pre-Authenticated and using bean based configuration as opposed to <http> namespace based configuration (in which case this appears to be trivial.
My config file is as follows:
<beans:bean id="springSecurityFilterChain"
class="org.springframework.security.web.FilterChainProxy">
<filter-chain-map path-type="ant">
<filter-chain pattern="/**/resources/**" filters="none" />
<filter-chain pattern="/**/logout/**" filters="none" />
<filter-chain pattern="/service/**" filters="none" />
<filter-chain pattern="/**"
filters="sif,concurrencyFilter,shibbolethFilter,smf,logoutFilter,etf,fsi" />
</filter-chain-map>
</beans:bean>
<beans:bean id="sif"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />
<beans:bean id="scr"
class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />
<beans:bean id="smf"
class="org.springframework.security.web.session.SessionManagementFilter">
<beans:constructor-arg name="securityContextRepository"
ref="scr" />
<beans:property name="sessionAuthenticationStrategy"
ref="sas" />
</beans:bean>
<beans:bean id="shibbolethFilter"
class="PreAuthenticatedShibbolethAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="exceptionIfHeaderMissing" value="true" />
<beans:property name="continueFilterChainOnUnsuccessfulAuthentication"
value="true" />
<beans:property name="developmentMode" value="true" />
<beans:property name="authenticationSuccessHandler"
ref="customAuthenticationSuccessHandlerBean" />
</beans:bean>
<beans:bean id="sas"
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:constructor-arg name="sessionRegistry"
ref="sessionRegistry" />
<beans:property name="maximumSessions" value="1" />
</beans:bean>
<beans:bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
<beans:bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<beans:property name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="expiredUrl" value="/session-expired.html" />
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref='preauthAuthProvider' />
</authentication-manager>
<beans:bean id="preauthAuthProvider"
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService">
<beans:bean id="userDetailsServiceWrapper"
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<beans:property name="userDetailsService" ref="userDetailsService" />
</beans:bean>
</beans:property>
</beans:bean>
<beans:bean id="logoutHandlerBean"
class="LogoutSuccessHandlerImpl" />
<beans:bean id="userDetailsService"
class="CustomJdbcDaoImpl">
<beans:property name="dataSource" ref="projectDS" />
<beans:property name="enableGroups" value="true" />
<beans:property name="enableAuthorities" value="false" />
</beans:bean>
In my controller I have the following code:
#Resource(name="sessionRegistry")
private SessionRegistry sessionReg;
private void doTest() {
List<Object> principals = sessionReg.getAllPrincipals();
for (Object o : principals) {
List<SessionInformation> siList = sessionReg.getAllSessions(o,
true);
for (SessionInformation si : siList) {
logger.error(si.getSessionId() + " " + si.getPrincipal());
}
}
}
The list principals is always empty. I feel the PreAuthenticatedShibbolethAuthenticationFilter filter which extends AbstractPreAuthenticatedProcessingFilter should get a ref to ConcurrentSessionControlStrategy, however, there is no such property which could be set.
What am I missing?
SecurityContextPersistenceFilter requires a SecurityContextRespository
<bean id="sif" class="org.springframework.security.web.context.SecurityContextPersistenceFilter" >
<property name="securityContextRepository" ref="scr" />
</bean>

Spring Security Ldap remember me not working

I have an application which uses spring security 3.0. The application uses my company's Active directory for login. I borrowed some of the code from the examples on the net and now I am able to successfully perform a bind. But the remember-me functionality is not working. To be more specific, I am able to sign into the application but when I close the browser and open the application it is redirecting to the login page again. Can anyone please tell me what is wrong in my configuration.
Security.xml
<http path-type="regex" use-expressions="true" auto-config="true">
<form-login
login-page="/Login.html"
login-processing-url="/j_spring_security_check"
default-target-url="/home.html"
authentication-failure-url = "/Login.html?login_error=1"
/>
<logout logout-success-url="/Login.html" invalidate-session="true"
delete-cookies="JSESSIONID" />
<intercept-url pattern="\A/Login\Z" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="\A/(?!Login).*\Z" access="isAuthenticated()" />
<remember-me key="_spring_security_remember_me" token-validity-seconds="3600" user-service-ref="ldapUserDetailsService"/>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="ldapAuthProvider"/>
</authentication-manager>
<beans:bean class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider" id="ldapAuthProvider">
<beans:constructor-arg ref="ldapBindAuthenticator"/>
<beans:property name="userDetailsContextMapper" ref="ldapUserDetailsContextMapper"/>
</beans:bean>
<beans:bean class="org.springframework.security.ldap.DefaultSpringSecurityContextSource" id="ldapServer">
<!-- MS Active Directory -->
<beans:constructor-arg value="ldap://hostname/DC=myCompany,DC=com"/>
<beans:property name="userDn" value="CN=user,OU=Users,DC=mycompany,DC=com"/>
<beans:property name="password" value="xxxxxx"/>
</beans:bean>
<beans:bean class="org.springframework.security.ldap.authentication.BindAuthenticator" id="ldapBindAuthenticator">
<beans:constructor-arg ref="ldapServer"/>
<beans:property name="userSearch" ref="ldapSearchBean"/>
</beans:bean>
<beans:bean class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch" id="ldapSearchBean">
<beans:constructor-arg value="OU=Users"/>
<beans:constructor-arg value="(sAMAccountName={0})"/>
<beans:constructor-arg ref="ldapServer"/>
</beans:bean>
<beans:bean class="org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper" id="ldapUserDetailsContextMapper"/>
<beans:bean id="ldapUserDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
<beans:constructor-arg index="0">
<beans:ref local="ldapSearchBean" />
</beans:constructor-arg>
</beans:bean>
<!-- Bean used for LDAP querying. -->
<beans:bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<beans:constructor-arg ref="ldapServer" />
</beans:bean>
<beans:bean class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" id="expressionHandler"/>

Unable to make Spring 3 Session Concurency Control work

Using Spring Security 3.1.0, I cannot seem to get the concurrent session control feature to work. When I log into my system at the same time using IE and FireFox (using my local workstation) I see my user principle in the session registry twice. I am expecting the concurrent session control to log me out or throw an exception or do something that indicates I am logged into the site more than once and it is not permitted.
For what it's worth, I could not get the concurrency control to work at all using the auto config of the HTTP namespace element, even with specifying that my site uses a custom login form. I'm wondering if that might be due to the fact that my authentication is provided via LDAP...?
Here's my security config.
<?xml version="1.0" encoding="UTF-8"?>
<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"
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.xsd">
<http auto-config="false" use-expressions="true" entry-point-ref="authenticationProcessingFilterEntryPoint">
<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
<custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter"/>
<session-management session-authentication-strategy-ref="sas"/>
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/css/**" access="permitAll" />
<intercept-url pattern="/images/**" access="permitAll" />
<intercept-url pattern="/js/**" access="permitAll" />
<intercept-url pattern="/public/**" access="permitAll" />
<intercept-url pattern="/home/**" access="permitAll" />
<intercept-url pattern="/admin/user/**" access="hasRole('AUTH_MANAGE_USERS')" />
<intercept-url pattern="/admin/group/**" access="hasRole('AUTH_MANAGE_USERS')" />
<intercept-url pattern="/**" access="isAuthenticated()" />
<access-denied-handler error-page="/403.html"/>
<logout invalidate-session="true" logout-success-url="/public/home.do"/>
</http>
<beans:bean id="authenticationProcessingFilterEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/public/login.do"/>
<beans:property name="forceHttps" value="false"/>
</beans:bean>
<beans:bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<beans:property name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="expiredUrl" value="/expired.html" />
</beans:bean>
<beans:bean id="myAuthFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="sessionAuthenticationStrategy" ref="sas" />
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="maximumSessions" value="1" />
<beans:property name="exceptionIfMaximumExceeded" value="true"/>
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref='ldapProvider' />
<authentication-provider ref="externalUserLdapProvider"/>
</authentication-manager>
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
<beans:bean id="securityContext"
class="org.springframework.security.core.context.SecurityContextHolder" factory-method="getContext"/>
<beans:bean id="ldapProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<beans:constructor-arg ref="bindAuthenticator" />
<beans:constructor-arg ref="userService" />
<beans:property name="userDetailsContextMapper" ref="permissionedUserContextMapper" />
</beans:bean>
<beans:bean id="permissionedUserContextMapper"
class="...service.impl.PermissionedUserContextMapperImpl" >
<beans:property name="userDao" ref="userDao"/>
</beans:bean>
<!-- LDAP via AD-->
<beans:bean id="bindAuthenticator"
class="org.springframework.security.ldap.authentication.BindAuthenticator">
<beans:constructor-arg ref="contextSource" />
<beans:property name="userSearch" ref="userSearch" />
</beans:bean>
<beans:bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<beans:constructor-arg>
<beans:value></beans:value>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:value>(sAMAccountName={0})</beans:value>
</beans:constructor-arg>
<beans:constructor-arg ref="contextSource" />
<beans:property name="searchSubtree">
<beans:value>true</beans:value>
</beans:property>
</beans:bean>
<beans:bean id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<beans:constructor-arg
value="ldap://omitted" />
<beans:property name="userDn"
value="ommitted" />
<beans:property name="password" value="omitted" />
</beans:bean>
<!-- Second LDAP Authenticator (Apache DS) -->
<beans:bean id="externalUserLdapProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<beans:constructor-arg ref="externalUserBindAuthenticator"/>
<beans:constructor-arg ref="userService" />
<beans:property name="userDetailsContextMapper" ref="permissionedUserContextMapper" />
</beans:bean>
<beans:bean id="externalUserBindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
<beans:constructor-arg ref="externalUserContextSource" />
<beans:property name="userDnPatterns">
<beans:list>
<beans:value>cn={0},ou=Users</beans:value>
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="externalUserContextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<beans:constructor-arg value="ldap://omitted"/>
</beans:bean>
</beans:beans>
Am I missing some property that should tell the concurrency control strategy to barf if the user logs more than 1 session? I know the same user is logging more than one session -- as I am seeing duplicate principles in the session registry.
Any/all replies are very much appreciated! Thanks in advance!
SessionRegistry uses equals()/hashCode() of UserDetails to find sessions of the same user. If you have custom UserDetails, perhaps it's not implemented.

Resources