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!";
}
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);
}
}