How to check that user has already logged in using

2020-07-27 05:31发布

问题:

The question is very simple. I'd like to restrict user access with same login from different machines/browsers: only one live user session is possible.

Apache shiro library is used for user authentification and managment.

Of course this could be done using simple synchornized maps and etc. But the question is: Has Apache Shiro special mechanisms for that or not?

Another variant of this question: how to reveice the list of all subjects who are logged in the system using apache shiro?

UPD:

To clarify my question. My desire is to have some code like this (I known, that there isn't such class exception, but the idea must be more clean):

Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(login, password);
try {
    currentUser.login(token);
} catch (AlreadyAuthenticatedException aae) {
    errorMsg = "You should logoff on another machine!";
}

回答1:

The Shiro sessions are stored in SessionDAO with sessionId as keys. Without extra effort you cannot access a session by a principal (user name). However, you could extend DefaultSecurityManager and check all active sessions by SessionDAO.getActiveSessions. The following codes could be a simple example (suppose you are not using WebSubject):

public class UniquePrincipalSecurityManager extends org.apache.shiro.mgt.DefaultSecurityManager {

    @Override
    public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException {

        String loginPrincipal = (String) token.getPrincipal();
        DefaultSessionManager sm = (DefaultSessionManager) getSessionManager();
        for (Session session : sm.getSessionDAO().getActiveSessions()) {
            SimplePrincipalCollection p = (SimplePrincipalCollection) session
                    .getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
            if (p != null && loginPrincipal.equals(p.getPrimaryPrincipal())) {
                throw new AlreadyAuthenticatedException();
            }

        }
        return super.login(subject, token);
    }

}