Spring security max session allowed - spring

I'm using spring security 3.1.4 and i would like to limit the number of session per user to 1 but if someone tries to log in it will close the old session and open a new one (instead of not allowing to log in) how can i do this?
EDIT:
this is what i added to the xmls:
web.xml
<listener>
<listener-class>
com.net.filter.session.SessionListener
</listener-class>
</listener>
SessionListener extends HttpSessionEventPublisher
security.xml
<security:intercept-url pattern="/**"
access="isAuthenticated()" />
<security:session-management>
<security:concurrency-control
max-sessions="1"/>
</security:session-management>
<security:form-login
authentication-success-handler-ref="playerAuthenticationSuccessHandler" />
<security:logout logout-url="/player/logout"
success-handler-ref="playerLogoutSuccessHandler" delete-cookies="JSESSIONID" />
</security:http>
<bean id="bCryptPasswordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<security:authentication-manager>
<security:authentication-provider
ref="authenticationProvider">
</security:authentication-provider>
</security:authentication-manager>
were playerAuthenticationSuccessHandler, authenticationProvider and playerLogoutSuccessHandler extends the spring defaults.

Related

Invoke Spring security with RestTemplate

I am new to spring security and I am confused over how spring security works. I have a filter chain defined as follows:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/rest/internal/*</url-pattern>
<url-pattern>/user/*</url-pattern>
<url-pattern>/http/*</url-pattern>
</filter-mapping>
and my security config looks as follows:
<global-method-security pre-post-annotations="enabled"/>
<http entry-point-ref="aligneUnauthorisedEntryPoint" use-expressions="true" create-session="never">
<!--<intercept-url pattern="/user/login" access="isAuthenticated()"/>-->
<intercept-url pattern="/rest/internal/**" access="isAuthenticated()"/>
<intercept-url pattern="/http/**" access="isAuthenticated()"/>
<custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER"/>
<custom-filter ref="logoutFilter" position="LOGOUT_FILTER"/>
<csrf disabled="true"/>
<http-basic/>
</http>
<authentication-manager alias="aligneAuthenticationManager">
<authentication-provider ref="aligneUserAuthenticationProvider"/>
</authentication-manager>
<beans:bean id="loginFilter" class="com.altra.middleware.security.AligneAuthenticationFilter">
<beans:property name="authenticationManager" ref="aligneAuthenticationManager"/>
<beans:property name="authenticationFailureHandler" ref="aligneAuthenticationFailureHandler"/>
<beans:property name="authenticationSuccessHandler" ref="aligneAuthenticationSuccessHandler"/>
<beans:property name="filterProcessesUrl" value="/user/login"/>
</beans:bean>
When i am hitting the following URL from my browser:
http://localhost:9099/jedi/rest/internal/main/dropdown
I get the following error.
Secondly, same exception comes occurs when i try to invoke the service from another spring controller using RestTemplate.
HTTP ERROR 503 Problem accessing /jedi/rest/internal/main/dropdown.
Reason:
Full authentication is required to access this resource
where /jedi is the application context.
If i comment out <intercept-url pattern="/rest/internal/**" access="isAuthenticated()"/> then the correct controller's method is called.
What is the significance of access="isAuthenticated()" ? We have this method overridden but it never gets called.
How should i go about this problem ?

How to implement ResourceUrlEncodingFilter with spring security

I am working on application which is using spring 3.2.3.RELEASE and Spring Security 3.1.4.RELEASE. I want to implement static resource versioning in my application. I did implement this functionality with spring 4.3.11 with this reference http://www.baeldung.com/cachable-static-assets-with-spring-mvc i.e, working fine. Now when I am going to implement this with my old application i.e, not working.I am providing you the code snippet
In my web.xml
<filter>
<filter-name>resourceUrlEncodingFilter</filter-name>
<filter-class>
org.springframework.web.servlet.resource.ResourceUrlEncodingFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>resourceUrlEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
In spring.xml
<security:http auto-config="true" pattern="/**" use-expressions="true">
<!-- Login pages -->
<security:form-login login-page="/login"
default-target-url="/home/"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/login?error" />
<security:logout logout-success-url="/home/"/>
<!-- Security zones -->
<security:intercept-url pattern="/favicon.ico" access="hasRole(ROLE_ANONYMOUS)" />
<security:intercept-url pattern="/login" access="permitAll"/>
<security:intercept-url pattern="/resources/**" access="permitAll"/>
<security:intercept-url pattern="/admin/**" access="hasRole('ROLE_SUPER_USER')" />
<security:intercept-url pattern="/**" access="isAuthenticated()" />
</security:http>
We are also using the caching filter in dispatcher servlet
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/resources/**" />
<bean id="responseCachingFilter" class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="cacheSeconds" value="0" />
<property name="useExpiresHeader" value="true" />
<property name="cacheMappings">
<props>
<prop key="/resources/**">21600</prop>
</props>
</property>
</bean>
</mvc:interceptors>
</mvc:interceptor>
and the versioning code
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/")
.setCacheControl(CacheControl.maxAge(6, TimeUnit.HOURS))
.resourceChain(false)
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"))
.addTransformer(new CssLinkResourceTransformer());
}
but my versioning code is not working. Please suggest me where I need to change the code or other approach need to implement.
Thanks In advance

Spring security login-processing-url throws 405 request method POST not supported

i'm working with spring security 3.1.3 in a spring 3.2.0 project. I've configured two entry points for my security using spring security. The idea is to have a url like /enterprise_login where enterprise users should log in and other url like /login where normal users do their log in action. In my security configuration i've the next code
<security:global-method-security jsr250-annotations="enabled" pre-post-annotations="enabled" secured-annotations="enabled" />
<security:http pattern="/enterprise/**" auto-config="false" use-expressions="true" authentication-manager-ref="autenticationManagerUserEnterprise">
<security:intercept-url pattern="/enterprise/**" access="hasRole('ROLE_ENTERPRISE')" />
<security:intercept-url pattern="/enterprise_login" access="isAnonymous()" />
<security:form-login login-page="/enterprise_login" default-target-url="/" authentication-failure-url="/empresas_login_error" login-processing-url="/enterprise_login_process" />
<security:logout logout-success-url="/" delete-cookies="JSESSIONID"/>
<security:remember-me user-service-ref="enterpriseAuthenticationProvider"/>
<security:session-management invalid-session-url="/">
<security:concurrency-control max-sessions="2" error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
<security:http pattern="/**" auto-config="false" use-expressions="true" authentication-manager-ref="autenticationManagerUser">
<security:intercept-url pattern="/**" access="permitAll" />
<security:form-login login-page="/login" default-target-url="/" authentication-failure-url="/login_error" />
<security:logout logout-success-url="/" delete-cookies="JSESSIONID"/>
<security:remember-me user-service-ref="UserAuthenticationProvider"/>
<security:session-management invalid-session-url="/">
<security:concurrency-control max-sessions="2" error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
<security:authentication-manager id="autenticationManagerUserEnterprise">
<security:authentication-provider user-service-ref="enterpriseAuthenticationProvider">
<security:password-encoder hash="plaintext"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<security:authentication-manager id="autenticationManagerUser">
<security:authentication-provider user-service-ref="UserAuthenticationProvider">
<security:password-encoder hash="plaintext"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="enterpriseAuthenticationProvider" class="com.test.security.enterpriseAuthenticationProvider"></bean>
<bean id="UserAuthenticationProvider" class="com.test.security.UserDetailsServiceImp"></bean>
Then when I go to /enterprise_login form and submit the login data I get a "HTTP 405 - Request method 'POST' not supported" throwed by tomcat in the url /enterprise_login_process (the url configured to act as login-processing-url. I can't figure out where the problem is, any help is really appreciated.
PD: My web.xml looks like:
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>AT-2</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-config.xml
</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>tutorial.root</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-config.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
The issue is that the first configuration currently only matches on URLs that start with "/enterprise/" and the URL to process authentication is configured as "/enterprise_login_process". This means that submitting a POST to "/enterprise_login_process" will submit to the second configuration which is not trying to authenticate "/enterprise_login_process".
To fix this you need to ensure the http#pattern and the login-processing-url are aligned. For example:
<security:http pattern="/enterprise/**"
auto-config="false"
use-expressions="true"
authentication-manager-ref="autenticationManagerUserEnterprise">
<security:intercept-url pattern="/enterprise/login"
access="isAnonymous()" />
<security:intercept-url pattern="/**"
access="hasRole('ROLE_ENTERPRISE')" />
<security:form-login login-page="/enterprise/login"
default-target-url="/"
authentication-failure-url="/enterprise/login?error"
login-processing-url="/enterprise/login_process" />
<security:logout logout-success-url="/"
delete-cookies="JSESSIONID"/>
<security:remember-me
user-service-ref="enterpriseAuthenticationProvider"/>
<security:session-management invalid-session-url="/">
<security:concurrency-control max-sessions="2"
error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
You will observe that I modified the code to ensure all URLs within the block start with "/enterprise/". This also means that you will need to ensure that your login form for enterprise is updated to POST to "/enterprise/login_process".

Spring-security :The page isn't redirecting properly

i want to use spring security from spring in m web application so here's the configuration:
This is the spring-security.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.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http auto-config="true" use-expressions="false">
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page="/authentication" login-processing-url="/static
/j_spring_security_check" authentication-failure
url="/login?login_error=t" />
</http>
<authentication-manager>
<authentication-provider>
<jdbc-user-service id="userService"
data-source-ref="DataSource"
users-by-username-query="select name, password, true from person where name=?"
authorities-by-username-query="select name,'ROLE_USER' from person where
name=?" />
</authentication-provider>
</authentication-manager>
Web.xml :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns
/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>OTV_JSF_PrimeFaces_Spring_Hibernate</display-name>
<!-- Spring Context Configuration' s Path definition -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<!-- The Bootstrap listener to start up and shut down Spring's root
WebApplicationContext. It is registered to Servlet Container -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<!-- Project Stage Level -->
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!-- Welcome Page -->
<welcome-file-list>
<welcome-file>/home.xhtml</welcome-file>
</welcome-file-list>
<!-- JSF Servlet is defined to container -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Mapping with servlet and url for the http requests. -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class> org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
here's the application :
When i run the application , this URL is opened
http://localhost:8089/MVNOONPProject/authentication and i get this error :
`The page isn't redirecting properly
Firefox has detected that the server is redirecting the request for this address in
a way that will never complete.`
I'm sure it's a problem with the web.xml . But i didn't find how to solve it .
Thank you in advance
It usually makes sense to protect only proper web pages which would be JSF rendered ones here. For sure you should not intercept all urls or else login won't be possible. This assumes you have a working login page under /authentication.
<http auto-config="true" use-expressions="false">
<intercept-url pattern="/**/*.faces" access="ROLE_USER" />
<intercept-url pattern="/**/*.jsf" access="ROLE_USER" />
<intercept-url pattern="/**/*.xhtml" access="ROLE_USER" />
<form-login login-page="/authentication" login-processing-url="/static
/j_spring_security_check" authentication-failure
url="/login?login_error=t" />
</http>
Try 2 things
Add
< intercept-url pattern="/authentication" access="IS_AUTHENTICATED_ANONYMOUSLY" />
Add default-target-url in your form-login tag
default-target-url='/home.xhtml'
One more thing you are using a custom login page and your http auto-config="true" change it to false if you are using custom login page
So your security config should be like this (login-processing-url is also not needed)
<http auto-config="false" use-expressions="false">
<intercept-url pattern="/**" access="ROLE_USER" />
< intercept-url pattern="/authentication" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<form-login login-page="/authentication" authentication-failure
url="/login?login_error=t" default-target-url='/home.xhtml'/>
Thats because , you spring security configuration redirects cyclically.
try this ,
<http auto-config="true" use-expressions="false">
<intercept-url pattern="/login.jsp*" filters="none"/>
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page="/authentication" login-processing-url="/static
/j_spring_security_check" authentication-failure
url="/login?login_error=t" />
</http>
Edit
<http auto-config="true" use-expressions="false">
<intercept-url pattern="/authentication" filters="none"/>
<intercept-url pattern="/login.jsp*" filters="none"/>
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page="/authentication" login-processing-url="/static
/j_spring_security_check" authentication-failure
url="/login?login_error=t" />
</http>
Since the pattern="/**" intercepts all URL requests including login page itself, any user has to be logged in even to access the login page.. so after hours of trying, following did the trick for me..
<intercept-url pattern="/login**" access="ROLE_ANONYMOUS" />
<intercept-url pattern="/resources/**" access="ROLE_ANONYMOUS, ROLE_USER, ROLE_ADMIN" />
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login
login-page="/login"
default-target-url="/home"
authentication-failure-url="/login?error=true" />
Notice,
the order of intercept-url tags
pattern="/**" basically intercepts all url request, even resources like css and image file. that's why the second line is needed.
Other answers were quite close but weren't working with Spring MVC 3.2.3.RELEASE version
I think this might cause other problems in the future, so the better approach might be,
<intercept-url pattern="/admin*" access="ROLE_ADMIN" />
<intercept-url pattern="/user*" access="ROLE_USER, ROLE_ADMIN" />
<form-login
login-page="/login"
default-target-url="/home"
authentication-failure-url="/login?error=true" />

Max Concurrent sessions doesn't apply to same browser

i have configured max sessions to be 1 and set error-if-maximum-exceeded=true
i noticed two issues:
1- session-authentication-error-url doesn't work if there's authentication-failure-handler-ref configured, the authentication-failure-handler-ref takes precedence and then you will have to handle SessionAuthenticationException there and make needed logic.
2- if i have open session in chrome and try to login in firefox i get the SessionAuthenticationException but if i tried to login again in chrome (which already has an open session) i get login successful and doesn't get the SessionAuthenticationException
should i prevent the user from seeing login page if he's already authenticated ?
if that's correct, please advise how to do that.
i usually check for authenticated user as follows:
if(!SecurityContextHolder.getContext().getAuthentication().getPrincipal().equals("anonymousUser")){
// logged in user
}
here's my current configuration:
1- web.xml:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
2- applicationSecurity.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:p="http://www.springframework.org/schema/p"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
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-3.1.xsd">
<bean id="passwordEncoder"
class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
<constructor-arg value="256"/>
</bean>
<bean id="saltSource"
class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<property name="userPropertyToUse" value="username" />
</bean>
<bean id="customUserDetailsService"
class="com.myapp.faces.web.services.CustomUserDetailsService" />
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder ref="passwordEncoder">
<security:salt-source ref="saltSource" />
</security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="loginSuccessHandler" class="com.myapp.faces.web.services.LoginSuccessHandler">
<property name="defaultTargetUrl" value="/dashboard"/>
</bean>
<bean id="loginFailureHandler" class="com.myapp.faces.web.services.LoginFailureHandler" />
<security:http use-expressions="true" auto-config="true" >
<security:intercept-url pattern="/j_spring_security_check" access="permitAll" />
<security:intercept-url pattern="/faces/javax.faces.resource/**" access="permitAll"/>
<security:intercept-url pattern="/xmlhttp/**" access="permitAll" />
<security:intercept-url pattern="/resources/**" access="permitAll" />
<security:intercept-url pattern="**/faces/javax.faces.resource/**" access="permitAll" />
<security:intercept-url pattern="**/xmlhttp/**" access="permitAll" />
<security:intercept-url pattern="**/resources/**" access="permitAll" />
<security:intercept-url pattern="/login" access="permitAll"/>
<security:intercept-url pattern="/**" access="isAuthenticated()" />
<security:form-login
login-processing-url="/j_spring_security_check"
login-page="/login"
authentication-failure-handler-ref="loginFailureHandler"
authentication-success-handler-ref="loginSuccessHandler" />
<security:logout />
<security:session-management session-authentication-error-url="/login?error=3">
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
</security:session-management>
</security:http>
</beans>
I personally do it this way.
#RequestMapping(method=RequestMethod.GET)
public String login(Authentication authentication)
{
if((authentication != null) && authentication.isAuthenticated())
{
return "redirect:dashboard";
}
return viewResolver.getView(ViewConstants.LOGIN_PAGE);
}
The method above is used for requesting the login page.
I don't think there is a way to do it using only configuration though. I may be wrong.
EDIT :
Check this link

Resources