mchrobok
mchrobok

Reputation: 2027

Get all logged users in Spring Security

I would like to get list of all users which are currently logged in my application. I know, that I should inject SessionRegistry in my code to call getAllPrincipals() method. Unfortunatelly, I always get empty list. It seems that SessionRegistry is not populate and I don't know how to make it. I know, that on StackOverflow there are similar questions, but I still have problem with solving my problem. Firstly I add to my web.xml this code:

<listener>
    <listener-class>
        org.springframework.security.web.session.HttpSessionEventPublisher
    </listener-class>
</listener>

As I know it allows to get information about lifecycle (create, destroy) of sessions. And that's all. I have big problem with moving forward. My file with security beans is presented below:

<beans:bean id="successAuth" class="pl.fp.microblog.auth.SuccessAuth"/>
<beans:bean id="failureAuth" class="pl.fp.microblog.auth.FailureAuth"/>

<http auto-config="true">
    <intercept-url pattern="/" access="ROLE_USER" />
    <intercept-url pattern="/profile/*" access="ROLE_USER" />
    <form-login 
        login-page="/login"         
        authentication-success-handler-ref="successAuth"
        authentication-failure-handler-ref="failureAuth"
        username-parameter="username"
        password-parameter="password"           
        login-processing-url="/login_processing_url"
    />          
    <security:logout logout-url="/logout_processing_url"/>  
    <session-management>
        <concurrency-control max-sessions="1" session-registry-alias="sessionRegistry"/>
    </session-management>
</http>

<beans:bean id="saltProvider" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
    <beans:property name="userPropertyToUse" value="username"></beans:property>
</beans:bean>

<beans:bean id="userService" class="pl.fp.microblog.auth.UserService">
    <beans:property name="userDAO" ref="userDAO"/>
</beans:bean>

<authentication-manager>
    <security:authentication-provider user-service-ref="userService">
        <password-encoder hash="sha-256">
            <security:salt-source ref="saltProvider"/>
        </password-encoder>         
    </security:authentication-provider>
</authentication-manager>

Here I call getAllPrinciples() method:

@Transactional
@Controller
public class SiteController {
    @Autowired
    private UserDAO userDAO;
    @Autowired
    private SessionRegistry sessionRegistry;    

    @RequestMapping(value = "profile/{login}")  
    public String profilePage(@PathVariable String login, HttpServletRequest req) throws SQLException {     
        ...
        sessionRegistry.getAllPrincipals().size()
        ...     
        return "profile";               
    }
}

I tried to add session-managemenent code into my http, ConcurrentSessionFilter and similar things, but in fact I don't understand it. And the documentation is too complex for me. Does anyone could help me and tell step by step what to do next? Which beans should I add?

Upvotes: 6

Views: 12526

Answers (1)

zagyi
zagyi

Reputation: 17518

I think you are almost there. The only thing you've probably missed is the use of session-registry-alias. By using that attribute on the concurrency-control element you expose the session registry, so that it can be injected to your own beans. See the reference doc.

So what you need is:

<http auto-config="true">
...
    <session-management>
        <concurrency-control max-sessions="1" session-registry-alias="sessionRegistry"/>
    </session-management>
</http>

Now you have a reference to the session registry that will be populated by the ConcurrentSessionControlStrategy which is set up implicitly by the above configuration. To use it you would just inject it to your bean as normal:

<bean class="YourOwnSessionRegistryAwareBean">
    <property sessionRegistry="sessionRegistry"/>
</bean>

Please note that the above configuration will also restrict the number of concurrent sessions a user may have. If you don't want this restriction, you will have to forgo the convenience of the namespace configuration, because the namespace schema doesn't allow you to set the max-sessions attribute to -1. If you need help on how to wire up the necessary beans manually, the reference doc gives detailed instructions on that.

Upvotes: 6

Related Questions