What is SessionRegistry?
Maintains a registry of SessionInformation instances.What is SessionInformation?
Source: Spring Security 3 API for SessionRegistry
Represents a record of a session within the Spring Security framework.We begin by inquiring how to query the SessionRegistry. A search on Spring Security Reference 3 gives us the following information:
This is primarily used for concurrent session support.
Source: Spring Security 3 API for SessionInformation
Setting up concurrency-control, either through the namespace or using plain beans has the useful side effect of providing you with a reference to the SessionRegistry which you can use directly within your application ...Based on this reference we need to setup the concurrency control to access the SessionRegistry.
The getAllPrincipals() method supplies you with a list of the currently authenticated users. You can list a user's sessions by calling the getAllSessions(Object principal, boolean includeExpiredSessions) method, which returns a list of SessionInformation objects. You can also expire a user's session by calling expireNow() on a SessionInformation instance.
Source: 11.3.1 Querying the SessionRegistry for currently authenticated users and their sessions
Here's what we need to do:
1. "To use concurrent session support, you'll need to add the following to web.xml"
2. "In addition, you will need to add the ConcurrentSessionFilter to your FilterChainProxy."
We add this in the http tag
3. "The ConcurrentSessionFilter requires two properties, sessionRegistry, which generally points to an instance of SessionRegistryImpl, and expiredUrl, which points to the page to display when a session has expired.".
We add the concurrencyFilter bean and sessionRegistry bean.
4. "Authentication by mechanisms which perform a redirect after authenticating (such as form-login) will not be detected by SessionManagementFilter, as the filter will not be invoked during the authenticating request. Session-management functionality has to be handled separately in these cases."
This means we can not use the following form-login tag anymore
5. This means we set the auto-config property to false:
6. Because we disabled auto-config and removed the form-login tag, we must manually assign an AuthenticationEntryPoint:
7. And because we don't have an option to set the default success url, we must add our own handler:
8. And because we don't have an option to set the default failure url, we must add our own handler as well:
9. To activate these handlers, we need to assign them to an AuthenticationFilter:
10. The AuthenticationFilter references an authenticationManager. We are required to set this as an alias:
11. We need to replace the default AuthenticationFilter with our customized filter. We do this by adding it to the FilterChainProxy
12. Define a concrete concurrent control strategy (after all, this is what we really need to activate):
We're done with the steps.
Let's now examine our final Spring XML configurations. Remember we're still dealing with a Spring MVC application.
web.xml
spring-security.xml
spring-servlet.xml
applicationContext.xml
To test this configuration, we create a JSP that displays the a list of currently authenticated users along with their associated details.
To serve this JSP, we add a third request handler in our existing primary controller.
MainController
Notice we have injected the SessionRegistry:
To access all logged-in users, we called the following method:
sessionRegistry.getAllPrincipals()To access all sessions of the current user, we use the following:
sessionRegistry.getAllSessions()When we run this application, the logs show the following:
[DEBUG] Received request to show users page [DEBUG] Total logged-in users: 2 [DEBUG] List of logged-in users: [DEBUG] org.springframework.security.core.userdetails.User@31a92e: Username: jane; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER [DEBUG] org.springframework.security.core.userdetails.User@31dd0b: Username: john; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER [DEBUG] Total sessions including expired ones: 1 [DEBUG] Total sessions: 1And here's the actual JSP page:
To access the users page, enter the following URL:
http://localhost:8080/spring-security-sessionregistry/krams/main/usersThat's it. We've managed to setup a working Spring MVC 3 application that's secured by Spring Security. We've managed to enable concurrent session control and access session information of all currently authenticated users. We've just touched the surface of concurrent session control, specifically SessionRegistry.
The best way to learn further is to try the actual application.
Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring3-security-mvc-integration-tutorial/
You can download the project as a Maven build. Look for the spring-security-sessionregistry.zip in the Download sections.
You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run
|
Share the joy:
|

how about counting online visitor? sum of members and client?
ReplyDelete@sown, I believe those encompasses all of them. When you say visitor, members, client I think these are categorized as ROLES.
ReplyDeletesuppose that i have a list of all users that signed in to system and now are online.
ReplyDeletei nedd to expire some of them.
how to expire session?
i know that i can remove session from sessionRegistryImpl onject by using sessionRegistry.removeSessionInformation().
but it seems not enough and also must be removed from SecurityContextHolder.
can you have any ideas?
Call the expireNow() form the SessionInformation. I mentioned that in this tutorial.
ReplyDelete"etting up concurrency-control, either through the namespace or using plain beans has the useful side effect of providing you with a reference to the SessionRegistry which you can use directly within your application ...
The getAllPrincipals() method supplies you with a list of the currently authenticated users. You can list a user's sessions by calling the getAllSessions(Object principal, boolean includeExpiredSessions) method, which returns a list of SessionInformation objects. You can also expire a user's session by calling expireNow() on a SessionInformation instance.
Source: 11.3.1 Querying the SessionRegistry for currently authenticated users and their sessions"
Using Spring 3.1.0 RC3 I get
ReplyDeleteThe type GrantedAuthorityImpl is deprecated ,
and does
public Collection getAuthorities(Integer access) {
should be
public Collection getAuthorities(Integer access) {
public Collection ?
Thanks
oops delete my last comment ,fix :
ReplyDeleteusing Spring Security 3.1.0 RC3 I get
The type GrantedAuthorityImpl is deprecated ,
does
public Collection>grantedauthority< getAuthorities
should be
public Collection>GrantedAuthority< getAuthorities?
( In Comments I cant put the < > ,it erase it )
Thanks
I haven't checked the latest changes in Spring Security 3.1.0.RC3 for this tutorial, though I have implemented it on other projects. If indeed that class is deprecated, I suggest you use the latest implementation. It should be relatively the same.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteFirst off, thanks so much for all the tutorials...they've all been a massive help.
ReplyDeleteMy understanding is that with the http auto-config set to "false" I'll need to configure remember-me myself. I tried adding the following:
security:custom-filter position="REMEMBER_ME_FILTER" ref="rememberMeFilter"
bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter"
p:authenticationManager-ref="authenticationManager"
p:rememberMeServices-ref="rememberMeServices"
bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices"
p:userDetailsService-ref="userManager"
p:key="whatever"
I also added p:rememberMeServices-ref="rememberMeServices" to the authenticationFilter.
This configuration doesn't seem to work...any suggestions?
This comment has been removed by the author.
ReplyDeleteI thought this might help others out so here's what I did to get "remember me" working. If anyone notices anything I could have done better (or that is outright wrong) please let me know. Also, sorry for all the deleted comments.
ReplyDeleteIn <http> I removed
<logout />
and added
<security:custom-filter position="REMEMBER_ME_FILTER" ref="rememberMeFilter" />
<security:custom-filter position="LOGOUT_FILTER" ref="logoutFilter" />
Added the following property to the "authenticationFilter" bean:
p:rememberMeServices-ref="rememberMeServices"
Added the following provider to "authenticationManager" (after the existing provider):
<security:authentication-provider ref="rememberMeAuthenticationProvider" />
Added the following beans:
<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter"
p:rememberMeServices-ref="rememberMeServices"
p:authenticationManager-ref="authenticationManager" />
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices"
p:userDetailsService-ref="userManager"
p:key="springRocks" />
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider"
p:key="springRocks" />
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter"
p:filterProcessesUrl="/auth/logout">
<constructor-arg value="/auth/login" />
<constructor-arg>
<list>
<ref bean="rememberMeServices" />
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
</list>
</constructor-arg>
</bean>
@aron, thanks for the feedback and sharing your configuration. I'm sorry if I wasn't able to respond promptly.
ReplyDeleteI couldn't find all the information in sessionRegistry.getAllPrincipals() except only the username when using customAuthenticationManager rather than authenticationManager. Need a help about it.
ReplyDeleteThanks in advance.
the reason you don't find that information in sessionRegistry is that you return in method authenticate (in CustomAuthenticationManager):
ReplyDelete.....
return new UsernamePasswordAuthenticationToken(
auth.getName(),
auth.getCredentials(),
getAuthorities(user.getAccess()));
....
You pass username as principal from auth.getName(), instead you could pass a UserDetails implementation so you can get user information from sessionRegistry and not just the username.
This is very interesting and give great information on Spring security. I am trying to create user/pwd to DB, i used MD5 encryption for pwd, but when I login using spring security defined in this blog i am getting You have entered an invalid username or password!.but I am able to login using other users john/jane as defined in this blog. Am i doing something wrong
ReplyDeleteMessageDigest md;
md = MessageDigest.getInstance("MD5");
byte[] passBytes = pass.getBytes();
md.reset();
byte[] digested = md.digest(passBytes);
StringBuffer sb = new StringBuffer();
for(int i=0;i<digested.length;i++){
sb.append(Integer.toHexString(0xff & digested[i]));
}