i need to invalidate ( or kick ) user session. the application only limit user login only one user per container.
i try to call removeSessionInformation from session registry, its done to unlock the user. so the other user can login with the kicked session user name.
but SessionContextHolder at that user that been kicked is still. so they still have the same authority to access the protected page.
how to invalidate or remove Principal of SessionContextHolder from specified session registry information?
ps : in my old application, i give one variable in UserDomain (UserDetails) that hold HttpSession. and when they need to kick the user, i just invalidate HttpSession from specified UserDomain. the but i don't know how to do it in spring (its more likey to remove Principal of SessionContextHolder than HttpSession). implementation is almost the same with how SessionRegistryImpl do in spring.
You may like to consider Spring Security Concurrency Control. You can configure this to limit the number of concurrent sessions per user and expire (kick) existing sessions if that number is exceeded.
Spring Security Session Management
This is a snippet of our configuration (Spring 3):
<http>
...
<session-management>
<concurrency-control max-sessions="1"/>
</session-management>
...
</http>
I'd guess this is the way to do it:
SecurityContextHolder.getContext().setAuthentication(null)
From the SecurityContext.setAuthentication(Authentication) Javadocs:
Changes the currently authenticated
principal, or removes the
authentication information.
Parameters: authentication
- the new
Authentication token, or null if no
further authentication information
should be stored
You can also do the following to clear the SpringSecurity Session:
SecurityContextHolder.clearContext()
This is extracted from my application-security.xml
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy"
p:maximumSessions="1" <br>
**p:exceptionIfMaximumExceeded="true"** >
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
try adding the line in bold letters after the maximum sessions number
Related
Spring's SecurityContextLogoutHandler notes that the clearAuthentication flag is used to:
removes the Authentication from the SecurityContext to prevent issues with concurrent requests.
What specific issue is being prevented by removing the Authentication from the SecurityContext? Why isn't simply invalidating the session (which is the other responsibility of SecurityContextLogoutHandler) sufficient?
By not clearing the SecurityContext is the concern that a SecurityContextPersistenceFilter may preserve the current authentication to a new session id? Effectively leaving the user logged in just with a new session?
What is SecurityContextLogoutHandler?
SecurityContextLogoutHandler is a handler which implements LogoutHandler.
What SecurityContextLogoutHandler does?
It performs a logout by modifying the SecurityContextHolder.
It will also invalidate the HttpSession if isInvalidateHttpSession()
is true and the session is not null.
It will also remove the Authentication from the current
SecurityContext if clearAuthentication is set to true (default).
Is SecurityContextHolder thread safe?
Yes, it's thread safe with the default strategy (MODE_THREADLOCAL) (as long as you don't try to change the strategy on the fly). However, if you want spawned threads to inherit SecurityContext of the parent thread, you should set MODE_INHERITABLETHREADLOCAL.
Also aspects don't have any "threading logic", they are executed at the same thread as the advised method.
Credit goes to #axtavt
What is authentication in Spring Security?
Authentication: The framework tries to identify the end user with the provided credentials. The authentication can be done against a third party system plugged into Spring Security.
Let's consider a standard authentication scenario that everyone is familiar with.
A user is prompted to log in with a username and password.
The system (successfully) verifies that the password is correct for
the username.
The context information for that user is obtained (their list of
roles and so on).
A security context is established for the user
The user proceeds, potentially to perform some operation which is potentially protected by an access control mechanism which checks the required permissions for the operation against the current security context information.
The first three items constitute the authentication process so we'll take a look at how these take place within Spring Security.
The username and password are obtained and combined into an instance
of UsernamePasswordAuthenticationToken (an instance of the
Authentication interface, which we saw earlier).
The token is passed to an instance of AuthenticationManager for
validation.
The AuthenticationManager returns a fully populated Authentication
instance on successful authentication.
The security context is established by calling
SecurityContextHolder.getContext().setAuthentication(...), passing
in the returned authentication object.
SecurityContextPersistentFilter
The name is quite explicit. The SecurityContextPersistentFilter interface purpose is to store the security context in some repository.
To achieve this task, the filter delegates the job to a SecurityContextRepository interface.
Spring provides a default implementation for this interface: org.springframework.security.web.context.HttpSessionSecurityContextRepository. This is quite self-explanatory. The repository for the security context is simply the current user HTTP session.
Below is the XML configuration for the SecurityContextPersistentFilter
<!-- Filter to store the Authentication object in the HTTP Session -->
<bean id="securityContextPersistentFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<property name="securityContextRepository" ref="securityContextRepository" />
</bean>
<bean id="securityContextRepository"
class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />
LogoutFilter
The LogoutFilter is in charge of logging out the current user and invalidating the security context. The task of invalidating the HTTP session is again delegated to another actor, the SecurityContextLogoutHandler.
This handler is injected in the LogoutFilter constructor:
<bean id="logoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/pages/Security/logout.html" />
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/j_myApplication_logout"/>
</bean>
<constructor-arg value="/pages/Security/logout.html" /> - it defines the URL of the logout page.
The SecurityContextLogoutHandler is injected as constructor argument at <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
The HTML URL for the logout action is define by the filterProcessesUrl parameter at <property name="filterProcessesUrl" value="/j_myApplication_logout"/>
Resource Link:
https://doanduyhai.wordpress.com/2012/01/22/spring-security-part-i-configuration-and-security-chain/
https://doanduyhai.wordpress.com/2012/02/05/spring-security-part-ii-securitycontextpersistentfilter-logoutfilter/
http://shazsterblog.blogspot.com/2014/02/spring-security-custom-filterchainproxy.html
http://docs.spring.io/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/context/SecurityContextPersistenceFilter.html
clearAuthentication flag was added in this commit with comment
Previously there was a race condition could occur when the user attempts to access
a slow resource and then logs out which would result in the user not being logged
out.SecurityContextLogoutHandler will now remove the Authentication from the
SecurityContext to protect against this scenario.
It fixed this issue (same issue on github). Quote:
HttpSessionSecurityContextRepository restores authentication to the session if session is invalidated from another thread if SecurityContextPersistenceFilter execution takes significant amount of time.
I am using Spring + JSF + DWR framework + GWT event service (ajax push). In any time there is at least one thread waiting at the server side for push events. This request is handled by SecurityContextPersistenceFilter which remembers the authentication at the moment of request's arriving to the server. If during the processing of this filter the session is being invalidated (by clicking logout in another tab of invalidating session by id from admin area) then HttpSessionSecurityContextRepository put the outdated authentication to the new session(which is created by JSF framework, so the session is changed during the processing of SecurityContextPersistenceFilter ).
This easily reproducable if some processing delay is inserted to SecurityContextPersistenceFilter.
SaveToSessionResponseWrapper should remember the initial HttpSession and check if the original session was invalidated so it won't set the current authentication to the new session.
http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html
Storing the SecurityContext between requests
Depending on the type of application, there may need to be a strategy in place to store the security context between user operations. In a typical web application, a user logs in once and is subsequently identified by their session Id. The server caches the principal information for the duration session. In Spring Security, the responsibility for storing the SecurityContext between requests falls to the SecurityContextPersistenceFilter, which by default stores the context as an HttpSession attribute between HTTP requests. It restores the context to the SecurityContextHolder for each request and, crucially, clears the SecurityContextHolder when the request completes. You shouldn't interact directly with the HttpSession for security purposes. There is simply no justification for doing so - always use the SecurityContextHolder instead.
Many other types of application (for example, a stateless RESTful web service) do not use HTTP sessions and will re-authenticate on every request. However, it is still important that the SecurityContextPersistenceFilter is included in the chain to make sure that the SecurityContextHolder is cleared after each request.
[Note] Note
In an application which receives concurrent requests in a single session, the same SecurityContext instance will be shared between threads. Even though a ThreadLocal is being used, it is the same instance that is retrieved from the HttpSession for each thread. This has implications if you wish to temporarily change the context under which a thread is running. If you just use SecurityContextHolder.getContext(), and call setAuthentication(anAuthentication) on the returned context object, then the Authentication object will change in all concurrent threads which share the same SecurityContext instance. You can customize the behaviour of SecurityContextPersistenceFilter to create a completely new SecurityContext for each request, preventing changes in one thread from affecting another. Alternatively you can create a new instance just at the point where you temporarily change the context. The method SecurityContextHolder.createEmptyContext() always returns a new context instance.
The SecurityContextLogoutHandler invalidates the Servlet session, in the standard Servlet way, calling the
invalidate method on the HttpSession object and also clearing the SecurityContext from Spring Security. SecurityContextLogoutHandler implements the LogoutHandler interface
Traditionally in Java web applications, user session information is managed with the HttpSession object.
In Spring Security(session clearing), at a low level, this is still the case ,
Spring security introduced new way of handling sessions or user session information.
In an application using Spring Security, you will rarely access the Session object directly for retrieving user
details. Instead, you will use SecurityContext (and its implementation class) and SecurityContextHolder
(and its implementing classes). The SecurityContextHolder allows quick access to the SecurityContext, the
SecurityContext allows quick access to the Authentication object, and the Authentication object allows quick
access to the user details.
for example following programing illustrates accesing authentication object and displaying message
#Controller
#RequestMapping("/admin")
public class AdminController {
#RequestMapping(method = RequestMethod.POST, value = "/movies")
#ResponseBody
public String createMovie(#RequestBody String movie) {
System.out.println("Adding movie!! "+movie);
return "created";
}
#RequestMapping(method = RequestMethod.GET, value = "/movies")
#ResponseBody
public String createMovie() {
UserDetails user = (UserDetails)SecurityContextHolder.getContext().getAuthentication().
getPrincipal();
System.out.println("returned movie!");
return "User "+user.getUsername()+" is accessing movie x";
}
}
once authentication is done it creates a new session is created;
Once session is created it contains information of user .on logout u need
not only to invalidate session but also need to clear the session information
by default in
`isInvalidateHttpSession(`)
checks whether session is valid or not
if session is valid
setInvalidateHttpSession(boolean invalidateHttpSession)
is called . howver invalidateing session object invalidates but session object still contains information.
to clear session information u need to call
setClearAuthentication(boolean clearAuthentication)
method thus becomes thread safe if u dont it third method it information can be retrieved at low level
I am working on a java application using spring security.
I want to avoid the session fixation, but the session fixation solution found on the docs seem not to be working as expected... here
So, I did this on my login
final HttpSession session = request.getSession(false);
if (session != null && !session.isNew()) {
session.invalidate();
}
Works great and changes the JSESSIONID everytime I call the login page...
But once I am logged in, I can call the login page again, get another JSESSIONID and still be logged in, I can just click on the back button and come back to the logged users area.
It does change the JSESSIONID, my question is, shouldnt it have a bigger effect? like invalidate my session or log me out?
When I call the log out form it does log the user out and works as expected, I am just wondering if changing the JSESSIONID has a real effect or does nto matter.
ANy idea?
I am using security 3.2
spring's session is mapped to JSESSIONID. so if a customer would have session state beans, they would be lost after changing JSESSIONID.
even though documentation tells
Spring Security protects against this automatically by creating a new
session when a user logs in
you can explicitly set configuration for session fixation by adding this
<security:session-management session-authentication-strategy-ref="fixation" />
and defining fixation bean with SessionFixationProtectionStrategy class
I'm working with a cas implementation and want to extend it by adding a separate spring-webflow. The webflow will be used to manage user specific data that is hosted in a separate web-service. This webflow will be restricted such that a user must first be authenticated in order to access it.
I've added a new flow to cas-servlet.xml as follows:
<webflow:flow-registry id="flowRegistry" flow-builder-services="builder">
...
<webflow:flow-location id="profile" path="/WEB-INF/profile-webflow.xml" />
...
</webflow:flow-registry>
The first state in my profile-webflow.xml is a view to a page that should display the users username ...
<view-state id="accessView" view="profileAccessView" />
The profileAccessView refers to profileAccessView.jsp which I want to display the username of the CAS authenticated user.
<h2>USERNAME</h2>
Is there a way to display the logged in users username here?
I've tried accessing and binding the user info via spring, but I get a null result, i.e. ...
SecurityContextHolder.getContext().getAuthentication()
In the CAS server, users are not authenticated by Spring Security. This question has been asked several times on the CAS mailing lists, I advice you to seek through them, like this one : https://groups.google.com/forum/#!searchin/jasig-cas-dev/username/jasig-cas-dev/-vMzR51b5S0/wbjpdMItHLMJ.
I have a custom AuthenticationProvider with the authenticate method.
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
> Check username, password, throw exceptions where needed
return new CustomAuthenticationToken(username, grantedAuthorities);
}
And the token:
public class CustomAuthenticationToken extends UsernamePasswordAuthenticationToken
{
public CustomAuthenticationToken(ICurrentUserContext currentUser, List<GrantedAuthority> authorities) {
super(currentUser.getUsername(), currentUser.getPassword(), authorities);
}
}
When I login with Chrome, Firefox, there is no problem whatsoever.
In IE 8/9 I have a very weird problem. Sometimes it will only call the method authenticate one time, it will login and everything works as expected. But from time to time, it will call authenticate twice, and fails to log in.
Does anybody have any clue?
I've tested it on Tomcat btw.
I've found the problem, with careful tracing the debug log of the Spring Security.. Hopefully this will help someone in the future.
Apparantly, spring security default migrates sessions after login. But in IE it does not migrate the authentication cookie to the new session, resulting in presenting of the login page.
The fix is easy, and can be done in the Spring Security xml:
<http use-expressions="true">
<!--
This settings is for IE. Default this setting is on migrateSession.
When IE tries to migrate the session, the auth cookie does not migrate,
resulting in a nice login screen again, after you've logged in.
This setting ensures that the session will not be invalidated, and thus IE will still work as expected.
-->
<session-management session-fixation-protection="none" />
</http>
Look at this please Internet Explorer buggy when accessing a custom weblogic provider.
Maybe you habe to disable cookies no your Tomcat
Migrating the session is entirely a server-side process and should be invisible to the browser. All it should see is a new Set-Cookie header for the JSESSIONID, which it should respect.
My best guess is that you are seeing this tomcat bug, which will cause different effects depending on how a browser interprets the duplicate headers. It was originally reported because of this issue with a Blackberry browser which is closely related to what you're seeing here.
But you don't say which versions of either Spring Security or Tomcat you are using (always a good idea :-)), so it's hard to say for sure.
Table of contents
Quick Reference
Spring Security Core plugin
<< 17IP Address Restrictions19Logout Handlers >>
18 Session Fixation Prevention - Reference Documentation
Authors: Burt Beckwith, Beverley Talbott
Version: 2.0-RC3
18 Session Fixation Prevention
To guard against session-fixation attacks set the useSessionFixationPrevention attribute to true:
grails.plugin.springsecurity.useSessionFixationPrevention = true
Upon successful authentication a new HTTP session is created and the previous session's attributes are copied into it. If you start your session by clicking a link that was generated by someone trying to hack your account, which contained an active session id, you are no longer sharing the previous session after login. You have your own session.
Session fixation is less of a problem now that Grails by default does not include jsessionid in URLs (see this JIRA issue), but it's still a good idea to use this feature.
Note that there is an issue when using the cookie-session plugin; see this issue for more details.
The table shows configuration options for session fixation.
Property Default Value Meaning
useSessionFixationPrevention true Whether to use session fixation prevention.
sessionFixationPrevention.migrate true Whether to copy the session attributes of the existing session to the new session after login.
sessionFixationPrevention.alwaysCreateSession false Whether to always create a session even if one did not exist at the start of the request.
http://grails-plugins.github.io/grails-spring-security-core/guide/sessionFixation.html
I have a custom-authentication-provider defined in my Spring Security configuration. This class implements AuthenticationProvider, and I can successfully log in using the form defined on my page. The issue is I want to call this class not just on the login page, but from the registration page as well.
The registration page uses a different command class and collects more information than the login form. Right now, when the user registers, I call the appropriate controller, add the record to the database and they can then log in but they aren't logged in automatically. As they've just given me their user name/password on the registration page, can I then pass this to the custom AuthenticationProvider class so they are also logged in?
I've tried creating an org.springframework.security.Authentication class in the registration controller and calling the authenticate method on my customer AuthenticationProvider class, and this doesn't error out, but the user isn't logged in. Do I have to call a method higher in the Spring Security filter chain to accomplish this? Should I redirect the controller to the j_spring_security_check URL? If so, how would I pass the username/password?
You need to put the result of AuthenticationProvider.authenticate() into SecurityContext (obtained from SecurityContextHolder).
Also be aware of AuthenticationSuccessEvent - if your application rely on this event (some Spring Security features may use it, too), you should publish it (you can obtain the default AuthenticationEventPublisher via autowiring). It may be useful to wrap your authentication provider with ProviderManager, it publishes the event automatically using the given publisher.
The problem you are having is that although you have successfully authenticated the user you have not stored the result of this authentication in the user's SecurityContext. In a web application this is a ThreadLocal object which the SecurityContextPersistenceFilter will use to store the user's credentials in the HTTPSession
You should also avoid authenticating directly with your custom authentication provider if you can. Your xml configuration should contain an AuthenticationManager which your custom authentication provider has been wired into. For example,
<bean id="customAuthenticationProvider"
class="com.foo.CustomAuthenticationProvider">
<property name="accountService" ref="accountService"/>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>
If you wire the authenticationManager into your registration service and authenticate using that it will additionally,
allow you to swap in/out additional authentication providers at later points
publish the authentication result to other parts of the Spring Security framework (eg success/failure Exception handling code)
Our registration service does this as follows
final UsernamePasswordAuthenticationToken authRequest = new
UsernamePasswordAuthenticationToken(username, password);
final Authentication authentication =
authenticationManager.authenticate(authRequest);
SecurityContextHolder.getContext().setAuthentication(authentication);
We also optionally store the authentication result at this point in a remember-me cookie using the onLoginSuccess() method of TokenBasedRememberMeServices.