Spring security concurrent session is not working as desired - session

Instead of restricting one session per user,it is restricting one session for
whole application.
So if one user is logged in noone can login .
Here is my configuration
<session-management invalid-session-url="/login">
<concurrency-control error-if-maximum-exceeded="true" max-sessions="1" />
</session-management>
And i even added listener in web.xml.
<?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.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- HTTP security configurations -->
<http auto-config="true" use-expressions="true">
<form-login login-processing-url="/resources/j_spring_security_check"
login-page="/login" default-target-url="/index"
authentication-success-handler-ref="myAuthenticationSuccessHandler"
authentication-failure-url="/login?login_error=t" />
<logout invalidate-session="true"
logout-url="/resources/j_spring_security_logout" success-handler-ref="myLogoutSuccessHandler"/>
<!-- Configure these elements to secure URIs in your application -->
<intercept-url pattern="/choices/**" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/member/**" access="isAuthenticated()" />
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/**" access="permitAll" />
<session-management invalid-session-url="/login">
<concurrency-control error-if-maximum-exceeded="true"
max-sessions="1" />
</session-management>
</http>
<!-- Configure Authentication mechanism -->
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customDaoAuthenticationProvider">
</authentication-provider>
</authentication-manager>
<beans:bean id="myAuthenticationSuccessHandler" class="com.test.connect.web.login.MyAuthenticationSuccessHandler"/>
<beans:bean id="myLogoutSuccessHandler" class="com.test.connect.web.login.MyLogoutSuccessHandler"/>
</beans:beans>

Based upon the configuration you provided, which includes a custom AuthenticationProvider, and the problem you are having I would guess that you are returning a custom UserDetails implementation that does not properly implement the equals and hashCode methods.
Please ensure that you have properly implemented equals and hashCode on any custom UserDetails implementation as these methods are used to look up if a user contains active sessions.

Just want to highlight here, make sure the equals and hashCode methods return is true. if the methods is not returning true it will not kill or terminate the existing session.

Related

Multiple spring security configuration not working

In my application i want to have separate spring security implementation based on url patterns.
Eg. /rest/ ** will have its own authentication provider(basic auth) and
/web/ ** will have its own authentication provider(form login).
please find below configuration i have done
<?xml version="1.0"?>
<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.xsd">
<!-- config for rest services using basic auth-->
<http pattern="/rest/**">
<intercept-url pattern="/MyAppRestServices" access="permitAll" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<http-basic />
</http>
<!-- AUTHENTICATION MANAGER FOR CUSTOM AUTHENTICATION PROVIDER -->
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProvider" />
</authentication-manager>
<!-- config for web using form login-->
<http pattern="/web/**">
<intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
<form-login/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="nimda" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
In above config first config is working fine ie restservice with basic auth but web with form login config is not working. its not even intercepting the url ?
Please let me know whats wrong with above config ?
Kindly refer below working configuration for web authentication::
<?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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<http pattern="/css/**" security="none" />
<http pattern="/images/**" security="none" />
<http pattern="/js/**" security="none" />
<http auto-config="false" authentication-manager-ref="dev" use-expressions="true" disable-url-rewriting="true">
<intercept-url pattern="/admin/login" access="permitAll" />
<intercept-url pattern="/admin/*" access="isAuthenticated()" />
<form-login
login-page="/admin/login"
default-target-url="/admin/workbench"
username-parameter="username"
password-parameter="password"
authentication-failure-url="/admin/login"
/>
<logout logout-success-url="/admin/login" logout-url="/j_spring_security_logout" invalidate-session="true" delete-cookies="JSESSIONID" />
</http>
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
<!-- STATIC USER -->
<authentication-manager id="dev" alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="abc" password="pwd" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>

<beans> to <beans:beans> - element beans must be declared

In the code below, why do I get "element must be declared" (From IntelliJ) if I change the start / end tags from "beans" to "beans:beans"?
What's the significance of the ":beans"?
<?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.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- HTTP security configurations -->
<http auto-config="true" use-expressions="true">
<form-login login-processing-url="/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" />
<logout logout-url="/j_spring_security_logout" />
<intercept-url pattern="/login" requires-channel="https"/>
<intercept-url pattern="/backend/**" access="isAuthenticated()" />
<intercept-url pattern="/todoes/**" access="isAuthenticated()" />
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/**" access="permitAll" />
<remember-me key="mySecondSecretWordThatShouldBeHidden" user-service-ref="userAccountDetailsService" />
</http>
<global-method-security secured-annotations="enabled" pre-post-annotations="enabled" />
<!-- Configure Authentication mechanism -->
<beans:bean name="passwordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder">
<beans:constructor-arg name="secret" value="myVerySecretWordThatShouldBeSomewhereHidden"/>
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userAccountDetailsService">
<password-encoder ref="passwordEncoder"/>
</authentication-provider>
</authentication-manager>
You have bound the security schema to the default namespace using xmlns=.... This means you can use the elements in that namespace directly without qualification, e.g. <authentication-manager>.
To use an element defined in another schema you need to bind that schema to another namespace and use that as a prefix. Declaring xmlns:beans="http://www.springframework.org/schema/beans" binds the schema identified by the URL to the namespace beans. The location of the schema is in the xsi:schemaLocation. Example usage <beans:bean>. Had you declared the namespace as xmlns:wibble="http://www.springframework.org/schema/beans", then this would change to <wibble:bean>.
You could have used any of them as your default namespace, which one makes sense depends on your config file and the types of bean it will have.

Spring security with multiple login pages

I am using Spring security to secure login to the application admin section with a username and password. But now my client need to have another login screen for the application clients section, where they will have their own usernames / passwords to login to the clients section. So far I've already implemented the admin section login successfully with the following spring-security.xml settings:
<security:http auto-config="true" use-expressions="true">
<security:form-login login-page="/login"
default-target-url="/admin/dashboard" always-use-default-target="true"
authentication-failure-url="/login/admin?error_msg=wrong username or password" />
<security:intercept-url pattern="/admin/*" access="hasRole('ROLE_ADMIN')" />
<security:logout logout-success-url="/login"/>
</security:http>
<security:authentication-manager>
<security:authentication-provider
user-service-ref="adminServiceImpl">
</security:authentication-provider>
</security:authentication-manager>
I've searched the web a lot trying to find how I can add the client section login screen, intercept-url(s), security authentication provider but couldn't find any info, so can someone please help me with any link to any tutorial / example, guide on how to do so?
Thanks
According to the Spring Security docs:
From Spring Security 3.1 it is now possible to use multiple http
elements to define separate security filter chain configurations for
different request patterns. If the pattern attribute is omitted from
an http element, it matches all requests.
Each element creates a filter chain within the internal FilterChainProxy and the URL pattern that should be mapped to it. The elements will be added in the order they are declared, so the most specific patterns must again be declared first.
So, essentially you need two <http> elements each with a different pattern attribute.
There's a detailed tutorial here: https://blog.codecentric.de/en/2012/07/spring-security-two-security-realms-in-one-application/
I would use only one security:http, but register two UsernamePasswordLoginFilters.
This solution would be appropriate if the two Login-Pages belog to the same security-realm. (So if it does not matter on which Login-Page the user logs in). Of course you can still use roles to restrict the access for different parts of your application for different types of users.
This solution should be quite easy, because you will not need to handle two security:http sections.
The major drawback of this is: that you will have to decide on which of the two login pages a NOT logged in user gets redirected if he try to access an page that requires a login.
Example project of Spring MVC App with multiple login forms.
Three types of pages Normal/Member/Admin.
If you try to access member page you are brought to Member Login form.
If you try to access admin page you go to the Admin Login form.
https://github.com/eric-mckinley/springmultihttploginforms
Done using the ant regex request matcher in the seucrity xml config file.
<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.xsd">
<global-method-security secured-annotations="enabled" />
<http name="member" pattern="/member/*" request-matcher="ant" auto-config="true" use-expressions="false">
<csrf disabled="true"/>
<intercept-url pattern="/member/home" access="ROLE_MEMBER" />
<intercept-url pattern="/member/account" access="ROLE_MEMBER" />
<intercept-url pattern="/member/orders" access="ROLE_MEMBER" />
<form-login login-page="/member-login" always-use-default-target="false"/>
<logout logout-url="/logout" logout-success-url="/home"/>
</http>
<http name="admin" request-matcher="regex" auto-config="true" use-expressions="false">
<csrf disabled="true"/>
<intercept-url pattern="/admin/home" access="ROLE_ADMIN" />
<intercept-url pattern="/admin/users" access="ROLE_ADMIN" />
<form-login login-page="/admin-login" always-use-default-target="false"/>
<logout logout-url="/logout" logout-success-url="/home"/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="password" authorities="ROLE_ADMIN" />
<user name="member" password="password" authorities="ROLE_MEMBER" />
<user name="super" password="password" authorities="ROLE_ADMIN,ROLE_MEMBER" />
</user-service>
</authentication-provider>
</authentication-manager>
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.0.xsd">
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/login" access="permitAll" />
<!-- <intercept-url pattern="/welcome/**" access="permitAll" /> <intercept-url
pattern="/admin*" access="hasRole('ROLE_ADMIN')" /> -->
<intercept-url access="hasRole('ROLE_USER')" pattern="/main*" />
<intercept-url pattern="/main*" access="hasRole('ROLE_USER')" />
<form-login login-page="/login" default-target-url="/login-success"
authentication-failure-url="/loginError" />
<!-- <session-management invalid-session-url="/login" session-fixation-protection="newSession">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management> -->
<logout logout-success-url="/login" delete-cookies="JSESSIONID" />
<csrf disabled="true" />
<headers>
<frame-options policy="SAMEORIGIN" />
</headers>
</http>
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/mobile/" access="permitAll" />
<intercept-url pattern="/mobile/login" access="permitAll" />
<!-- <intercept-url pattern="/welcome/**" access="permitAll" /> <intercept-url
pattern="/admin*" access="hasRole('ROLE_ADMIN')" /> -->
<intercept-url access="hasRole('ROLE_USER')" pattern="/main*" />
<intercept-url pattern="/main*" access="hasRole('ROLE_USER')" />
<form-login login-page="/mobile/login" default-target-url="/mobile/login-success"
always-use-default-target="true" authentication-failure-url="/mobile/login?error"
username-parameter="username" password-parameter="password" />
<logout delete-cookies="JSESSIONID" logout-success-url="/mobile/login" />
<csrf disabled="true" />
<headers>
<frame-options policy="SAMEORIGIN" />
</headers>
Here I have need two login forms common for all users. I have configured tag element as mentioned above in spring-security.xml.But it is not working. Please suggest me a solution

spring security redirects to last requested page after login session timeout

I have implemented spring security for login to my web portal. It works fine except for one issue. I have set session timeout to 5 min. Once timeout happpens and then user click any URL, it gets redirected to logout page.
But when user re autheticates, user directly lands on the last access page instead of home page which is default target URL.
Spring security file is as below:
<?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="true">
<intercept-url pattern="/index.jsp" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/home.html" access="ROLE_ADMIN,ROLE_USER" />
<intercept-url pattern="/mdm/accessToken.html" access="ROLE_USER" />
<intercept-url pattern="/mdm/enroll.html" access="ROLE_USER" />
<intercept-url pattern="/mdm/installApp.html" access="ROLE_USER" />
<intercept-url pattern="/mdm/checkStatus.html" access="ROLE_USER" />
<intercept-url pattern="/mdm/searchDevice.html" access="ROLE_USER" />
<intercept-url pattern="/admin/*" access="ROLE_ADMIN" />
<intercept-url pattern="/account/*" access="ROLE_ADMIN" />
<intercept-url pattern="/user/*" access="ROLE_USER" />
<form-login login-page="/login.html" default-target-url="/home.html"
authentication-failure-url="/loginfailed.html" />
<logout logout-url="/logout.html" logout-success-url="/logoutSuccess.html" invalidate-session="true" />
<anonymous username="guest" granted-authority="ROLE_GUEST" />
<session-management>
<concurrency-control max-sessions="1" />
</session-management>
<session-management invalid-session-url="/logout.html" />
</http>
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select USER as username, password, 'true' as enabled from TBL_USER_MASTER where user=?"
authorities-by-username-query="select um.USER as username , rm.ROLE_NAME as authorities from TBL_USER_MASTER um,TBL_ROLE_MASTER rm
where um.USER=? and um.role_id=rm.role_id" />
<password-encoder hash="md5"/>
</authentication-provider>
</authentication-manager>
</beans:beans>
Add the always-use-default-target attribute to your form-login tag.
<form-login always-use-default-target="true" />
If set to true, the user will always start at the value given by default-target-url, regardless of how they arrived at the login page. Maps to the alwaysUseDefaultTargetUrl property of UsernamePasswordAuthenticationFilter. Default value is false.
In Grails, this setting solves the problem in Config.groovy
grails.plugin.springsecurity.successHandler.alwaysUseDefault = true

Spring XML using <bean>

This is a pretty simple question, I'm following a tutorial and I'm up to the point where I'm adding a passwordEncoder to my spring security, I have the following 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"
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.1.xsd">
<http pattern="/static/**" security="none" />
<http use-expressions="true">
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/*" access="isAuthenticated()" />
<!-- <intercept-url pattern="/secure/extreme/**" access="hasRole('supervisor')"
/> -->
<!-- <intercept-url pattern="/listAccounts.html" access="isAuthenticated()"
/> -->
<!-- <intercept-url pattern="/post.html" access="hasAnyRole('supervisor','teller')"
/> -->
<!-- <intercept-url pattern="/*" access="denyAll" /> -->
<form-login />
<logout invalidate-session="true" logout-success-url="/"
logout-url="/logout" />
</http>
<authentication-manager>
<authentication-provider user-service-ref="customUserDetailsService">
<password-encoder ref="passwordEncoder"/>
</authentication-provider>
</authentication-manager>
<bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>
</beans:beans>
The problem is the <bean class="org.spr.. line just at the bottom is erroring saying security namespace does not allow
I do understand this, but is there a way I can use the reference without having to add <security: to everything else?
In your XML declaration you are declaring that "security:" is the default namespace:
xmlns="http://www.springframework.org/schema/security"
you have to preface all the elements not found in the security namespace with their prefix... in this case bean is in beans namespace... so you would need to say, beans:bean
This declaration:
<bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>
should be:
<beans:bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>

Resources