Tuesday, December 28, 2010

Spring Security - MVC: Querying the SessionRegistry

In this tutorial we will build a Spring MVC 3 application secured by Spring Security 3. We will explore how to retrieve currently logged-in users using the SessionRegistry. We will also explore how to retrieve their session information. We will focus on simple configuration. Our users will be authenticated based on Spring's built-in in-memory user-service. This tutorial will build on top of the Spring Security 3 - MVC: Using a Simple User-Service Tutorial because the only difference is mainly XML configuration. It's highly recommended that you read that first!

What is SessionRegistry?
Maintains a registry of SessionInformation instances.

Source: Spring Security 3 API for SessionRegistry
What is SessionInformation?
Represents a record of a session within the Spring Security framework.

This is primarily used for concurrent session support.

Source: Spring Security 3 API for SessionInformation
We begin by inquiring how to query the SessionRegistry. A search on Spring Security Reference 3 gives us the following information:
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 ...

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
Based on this reference we need to setup the concurrency control to access the SessionRegistry.

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: 1
And here's the actual JSP page:
To access the users page, enter the following URL:
http://localhost:8080/spring-security-sessionregistry/krams/main/users
That'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
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security - MVC: Querying the SessionRegistry ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

76 comments:

  1. how about counting online visitor? sum of members and client?

    ReplyDelete
  2. @sown, I believe those encompasses all of them. When you say visitor, members, client I think these are categorized as ROLES.

    ReplyDelete
  3. suppose that i have a list of all users that signed in to system and now are online.
    i 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?

    ReplyDelete
  4. Call the expireNow() form the SessionInformation. I mentioned that in this tutorial.

    "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"

    ReplyDelete
  5. Using Spring 3.1.0 RC3 I get

    The type GrantedAuthorityImpl is deprecated ,

    and does
    public Collection getAuthorities(Integer access) {

    should be

    public Collection getAuthorities(Integer access) {

    public Collection ?

    Thanks

    ReplyDelete
  6. oops delete my last comment ,fix :

    using 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

    ReplyDelete
  7. 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.

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. First off, thanks so much for all the tutorials...they've all been a massive help.

    My 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?

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. I 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.

    In <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>

    ReplyDelete
  13. @aron, thanks for the feedback and sharing your configuration. I'm sorry if I wasn't able to respond promptly.

    ReplyDelete
  14. I couldn't find all the information in sessionRegistry.getAllPrincipals() except only the username when using customAuthenticationManager rather than authenticationManager. Need a help about it.

    Thanks in advance.

    ReplyDelete
  15. the reason you don't find that information in sessionRegistry is that you return in method authenticate (in CustomAuthenticationManager):

    .....

    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.

    ReplyDelete
  16. 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
    MessageDigest 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]));
    }

    ReplyDelete
  17. Its all is too complicated....

    ReplyDelete
  18. This comment has been removed by the author.

    ReplyDelete
  19. session registry also returns recently logged out users in getAllPrincipals().

    ReplyDelete
  20. session registry also returns recently logged out users in getAllPrincipals.

    ReplyDelete
  21. getAllPrincipals returing a empty list please suggest

    ReplyDelete
  22. Hi, getAllPrincipals returns me an empty list:((( any ideas why?

    ReplyDelete
    Replies
    1. Do ye have this one in web.xml

      org.springframework.security.web.session.HttpSessionEventPublisher

      Delete
  23. How to avoid loading "applicationContext.xml" twice.

    ReplyDelete
    Replies
    1. Some one suggest that remove that remove "/WEB-INF/applicationContext.xml".

      Now problem while loading the "sessionRegistry" bean from the spring_security.xml conf file.

      Delete
  24. Doesn't work for me.
    sessionRegistry.getAllPrincipals() return an empty list.
    Any reason why ? I used the exact same config files as explained here.

    ReplyDelete
  25. Actually i developed one application same way but i am getting password by username from database in my CustomUserDetails and created User class and return to spring application context.If i configure like this, i not getting logged in users eventhough i am calling sessionRegistry.getAllPrincipals().(Every configuration is as it is like in this application)
    Please reply as earlier as possible.

    ReplyDelete
  26. please anybody reply for the above problem

    ReplyDelete
  27. Project is good working, no problem but there are some problems on steps. Although one of users log out the page by "/krams/auth/logout" url, no change in logged users list page. So, I think this is not working correctly.

    ReplyDelete
  28. Finding the time and actual effort to create a superb article like this is great thing. I’ll learn many new stuff right here! Good luck for the next post buddy..

    Best Industrial Training in Noida
    Best Industrial Training in Noida

    ReplyDelete
  29. Nice looking sites and great work. Pretty nice information. it has a better understanding. thanks for spending time on it.

    Best BCA Colleges in Noida

    ReplyDelete
  30. This is an awesome post.Really very informative and creative contents. These concept is a good way to enhance the knowledge.
    I like it and help me to development very well.Thank you for this brief explanation and very nice information.Well, got a good knowledge.
    Java training in Indira nagar
    Java training in Rajaji nagar
    Java training in Marathahalli
    Java training in Btm layout
    Java training in Marathahalli

    ReplyDelete
  31. Keunggulan situs judi BatuQQ dengan pelayanan livechat 24 jam, customer service yang handal dan sangat ramah, menyediakan 5 bank untuk memudahkan transaksi member, proses depo dan wd sangat cepat bahkan disaat bank offline proses depo tetap akan di proses dengan sangat cepat..
    Keunggulan dari situs domino BatuQQ Bandar Poker dari situs kami sebagai penyedia permainan online yaitu jaminan keamanan, dan privasi dari setiap data User ID seluruh member. Proses transaksi deposit, dan withdraw yang super cepat, serta pelayanan Customer Service yang professional, dan ramah. Di samping itu kami juga memberikan jaminan bahwa setiap transaksi yang ada di proses dalam waktu di bawah 3 menit, dan tidak ada batasan nominal dalam melakukan tarik dana di BatuQQ BandarQQ. ( Withdraw berapapun akan kami bayar )


    Batu4d online lottery consists of online lottery sites that provide 6 online lottery markets such as HONGKONG TOGEL, SINGAPORE TOGEL, LOTTERY PORKAS TOGEL, SYDNEY TOGEL, AUCKLAND TOGEL, PERTH TOGEL with all that can be done, fast deposit and withdrawal Batu4d togel online indonesia can be searched for lottery online. As the biggest togel site Batu4D holds a trusted online tagging site

    ReplyDelete
  32. Hi, It’s Amazing to see your blog.This provide us all the necessary information regarding
    upcoming real estate project which having all the today’s facilities.
    autocad in bhopal
    3ds max classes in bhopal
    CPCT Coaching in Bhopal
    java coaching in bhopal
    Autocad classes in bhopal
    Catia coaching in bhopal

    ReplyDelete
  33. This comment has been removed by the author.

    ReplyDelete
  34. This comment has been removed by the author.

    ReplyDelete
  35. Whatever we gathered information from the blogs, we should implement that in practically then only we can understand that exact thing sap business intelligence training clearly, but it’s no need to do it, because you have explained the concepts very well. It was crystal clear, keep sharing..

    ReplyDelete
  36. than nine countries to believe gclub But now there is an online casino system that makes people interested and like. Have the opportunity to come in to play without having to travel to a foreign

    ReplyDelete
  37. Pretty article! I found some useful information in your blog, it was awesome to read, thanks for sharing this great content to my vision, keep sharing...... sapui5 online training

    ReplyDelete
  38. First of all, must give credit to แทงบอล Watford. They deserve victory. When looking at the opportunities that they can create in this game They can play as planned. They scored three goals

    ReplyDelete
  39. Thanks for sharing such a great information..Its really nice and informative..

    sap bw tutorials

    ReplyDelete
  40. cool text. looking for companions for joint escort to จีคลับ . perhaps the highest chance of winning. wide offer of games. join in

    ReplyDelete
  41. pictures, clear, see more details, including สโบเบ็ต Gclub slots, lottery, boxing, baccarat, Fantan, Roulette

    ReplyDelete
  42. Very informative article which is about the refrigeration and i must bookmark it, keep posting interesting articles.

    ReplyDelete
  43. Darmowe spiny, 100% Bonus od depozytu lub inne możliwe nagrody przy rejestracji w kasynie Alf https://top10casinoexpert.pl/casino/alf-casino/

    ReplyDelete
  44. Sea Moss can be purchased online or from a local dealer to make sure they come from a reputable source! Buying Irish Sea Moss Capsules from a major retailer or online is acceptable, but check the product before buying. Make sure the Sea Moss products you buy are natural and vegan.

    ReplyDelete
  45. บาคาร่าออนไลน์***//*///*Every among the contents you outlined in publish is just also outstanding and may be really valuable. I'll maintain it within your brain, several thanks for sharing the information sustain updating, looking for forward For added posts.Quite a few thanks.https://in1.bet/.

    ReplyDelete