expresssession这样的中间件来管理会话。如果你使用的是Django框架,你可以使用Django自带的会话框架。,,为了提高安全性,你可能还需要考虑其他因素,比如防止会话劫持、使用HTTPS加密通信、存储安全的会话令牌等。要实现一个会员账号只允许单人实时登录,可以采用多种方法,以下是两种常见的实现方式:

方法一:使用数据库和拦截器
1、创建内存表:在数据库中创建一个内存表member_sessionid,包含两个字段MS_ID 和MS_SESSIONID。
2、添加用户记录:在创建用户时,在内存表中添加一条数据,字段MS_ID 为新建用户在用户表中的主键id,字段MS_SESSIONID 先设为空。
3、维护会话信息:用户登录成功之后,根据用户id 去内存表查询该用户的记录,如果该记录存在,将该记录的MS_SESSIONID 字段设置成当前会话的sessionId;如果不存在,在表中添加一条记录,MS_ID 设置为用户的id,MS_SESSIONID 设置为当前请求的sessionId。
4、添加拦截器:添加一个拦截器,每次请求服务器时(不包括登录请求、退出请求以及静态资源的请求),根据用户id 去内存表中查询用户的记录并取出该记录的MS_SESSIONID 字段,从请求中取出sessionId,和上面查出来的MS_SESSIONID 字段进行对比,如果不相等,执行退出操作。

public class SessionIdInterceptor implements HandlerInterceptor {
@Autowired
private MemberSessionidService memberSessionidService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String sessionId = request.getSession().getId();
String userId = request.getSession().getAttribute("id").toString();
MemberSessionid memberSessionid = memberSessionidService.selectById(Integer.parseInt(userId));
if (sessionId.equals(memberSessionid.getMsSessionid())) {
return true;
} else {
response.sendRedirect(request.getContextPath() + "/admin/reloadRemind");
return false;
}
}
}
5、配置拦截器:在拦截器配置列表中添加新的拦截器的配置。
<mvc:interceptor>
<mvc:mapping path="/**"/>
</mvc:interceptor>
方法二:使用应用配置和 Shiro
1、修改配置文件:在application.yml 文件中设置maxSession 为1即可限制一个账户同时只能一个人登录。
shiro:
session:
maxSession: 1
2、调整 Shiro 配置:修改 Shiro 的配置,使其支持单点登录。
shiro:
session:
kickoutAfter: false
3、新增常量:在Constants.java 中新增一个常量LOGIN_USERID_KEY 公用。

public static final String LOGIN_USERID_KEY = "login_userid:";
4、调整 TokenService:存储和刷新缓存用户编号信息。
@Value("${token.soloLogin}")
private boolean soloLogin;
public void delLoginUser(String token, Long userId) {
if (StringUtils.isNotEmpty(token)) {
String userKey = getTokenKey(token);
redisCache.deleteObject(userKey);
}
if (!soloLogin && StringUtils.isNotNull(userId)) {
String userIdKey = getUserIdKey(userId);
redisCache.deleteObject(userIdKey);
}
}
5、自定义退出处理类:清除缓存方法添加用户编号。
public class LogoutSuccessHandlerImpl extends AbstractShiroRealm {
// 删除用户缓存记录
tokenService.delLoginUser(loginUser.getToken(), loginUser.getUser().getUserId());
}
6、验证登录方法:在登录方法中验证如果用户不允许多终端同时登录,清除缓存信息。
@Value("${token.soloLogin}")
private boolean soloLogin;
protected void authenticated(HttpServletRequest request, User user) {
if (!soloLogin) {
tokenService.delLoginUser(loginUser.getToken(), loginUser.getUser().getUserId());
}
}
通过以上两种方法中的任意一种,可以实现一个会员账号只允许单人实时登录的功能,每种方法都有其优缺点,可以根据具体项目需求选择合适的实现方案。