问题很简单。我想限制来自不同机器/浏览器的相同登录的用户访问:只能进行一次实时用户会话。
Apache shiro
库用于用户身份验证和管理。
当然这可以使用简单的同步地图等来完成。但问题是:Apache Shiro
有特殊机制吗?
此问题的另一个变体:如何使用apache shiro
显示使用系统登录系统的所有主题列表?
UPD:
澄清我的问题。我的愿望是拥有这样的代码(我知道,没有这样的类异常,但想法必须更干净):
Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(login, password);
try {
currentUser.login(token);
} catch (AlreadyAuthenticatedException aae) {
errorMsg = "You should logoff on another machine!";
}
答案 0 :(得分:1)
Shiro会话存储在SessionDAO
中,sessionId
作为键。无需额外工作,您无法通过主体(用户名)访问会话。但是,您可以扩展DefaultSecurityManager
并按SessionDAO.getActiveSessions
检查所有活动会话。
以下代码可能是一个简单的示例(假设您没有使用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);
}
}