【发布时间】:2019-06-24 13:30:21
【问题描述】:
我想将每个用户的并发会话数限制为 1。如果用户从第二个客户端/IP 登录,我想使他以前的会话无效(如果有的话)并为当前客户端创建一个新会话。因此,如果用户从第一个客户端发出另一个请求,则应该拒绝访问并重定向用户。
我在我的 Spring 启动应用程序中使用 Shiro。它是一个纯粹的 API 服务器,而不是 Web 应用程序。前端和后端是分开的。
Shiro 似乎没有开箱即用的会话限制支持。
我想知道我应该在哪里执行操作?
目前我有自己的
public class AuthRealm extends AuthorizingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// Get user from db and return authentication info
}
}
不知道是不是一个干净的地方添加相应的逻辑?还是我应该在登录后的上一个会话中创建第二个客户端的会话?
我认为这样做可能更有意义
public class AuthRealm extends AuthorizingRealm {
@Override
protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
// Credentials verified
// Invalidate previous session
Subject subject = SecurityUtils.getSubject();
Session existingSession = subject.getSession(false);
if (existingSession != null) {
SecurityUtils.getSecurityManager().logout(subject);
existingSession.stop();
}
}
}
但事实证明,Shiro 创建了一个新主题,并绑定了一个新会话,每次登录,而不是每个用户。所以subject = SecurityUtils.getSubject() 将永远是一个全新的,并且不可能检索同一个用户然后检索其会话。有什么想法吗?
【问题讨论】:
-
您的 API 服务器是无状态的,还是希望客户端持有令牌/cookie?如果它是无状态的,并且您想将客户端限制为单个请求,您会发现某些 HTTP 客户端的工作方式具有挑战性,请参阅:medium.com/inloopx/… 此外,如果您启用了缓存,您的
doGetAuthenticationInfo方法将不会被调用,所以您会需要实施更高的东西。您最好的选择可能是某种过滤器。但是您也会增加使会话中间请求无效的风险
标签: spring-boot shiro