在线考试系统如何实现同账号仅允许单用户同时登录?
禁止同一账号多端同时登录适配在线考试场景的实现方案
核心思路是在原有登录状态标记方案的基础上,新增活跃状态自动续期+超时自动回收机制,既避免异常退出导致的登录状态永久占用问题,也不会出现后登录用户挤掉前登录用户的情况,完全适配在线考试的业务要求。
具体实现步骤
- 改造用户表存储结构
保留原有的login_status字段(0代表未登录,1代表已登录),额外新增3个字段:last_active_time:datetime类型,记录用户最后一次操作的时间戳current_login_token:varchar类型,存储当前登录用户的唯一会话凭证is_in_exam:tinyint类型,标记用户是否正在参与考试,用于特殊适配超时规则
- 调整登录校验逻辑
用户发起登录请求时按以下逻辑校验:- 校验账号密码有效性,验证不通过直接返回错误
- 查询对应用户的
login_status字段:- 若
login_status为0:允许登录,生成唯一token写入current_login_token,将login_status设为1,更新last_active_time为当前时间,同时把token存入用户的session或客户端cookie中 - 若
login_status为1:先计算当前时间与last_active_time的差值,和超时阈值比对- 差值超过阈值:判定原登录会话已失效,允许当前用户登录,按上述登录成功逻辑更新对应字段即可
- 差值未超过阈值:直接拦截登录请求,返回「当前账号已在其他设备登录,无法重复登录」提示
- 若
- 配置活跃状态续期规则
避免用户正常使用过程中被误判为会话失效:- 用户每触发一次业务操作(包括答题、交卷、页面切换等),同步更新该用户的
last_active_time为当前时间 - 前端新增心跳机制,每隔5分钟向后端发送一次空请求,即使用户没有主动操作,只要登录页面处于打开状态就自动续期
- 用户每触发一次业务操作(包括答题、交卷、页面切换等),同步更新该用户的
- 完善登出逻辑
覆盖正常和异常登出场景:- 用户主动点击登出按钮:直接将
login_status重置为0,清空current_login_token和last_active_time - 异常场景(断网、关闭浏览器、设备关机):依赖超时机制自动回收登录状态,只要用户超出阈值没有活跃记录,状态就会自动重置,不会出现账号永久被占用的问题
- 用户主动点击登出按钮:直接将
在线考试场景适配优化
- 用户进入考试页面后,将
is_in_exam标记设为1,同时把超时阈值临时调整为「考试剩余时长+15分钟」,避免考试过程中临时断网几分钟就被判定会话失效,导致其他设备可以登录的问题 - 用户提交试卷后,自动将
is_in_exam标记设为0,同时重置登录状态,释放账号占用
核心逻辑伪代码示例
# 登录校验伪代码 def user_login(username, input_password): user = query_user_by_username(username) if not password_verify(input_password, user.encrypted_password): return {"code": 400, "msg": "账号或密码错误"} # 登录状态校验 if user.login_status == 1: # 超时阈值配置,考试场景特殊处理 timeout_threshold = 30 * 60 # 默认30分钟超时 if user.is_in_exam: timeout_threshold = user.exam_remaining_time + 15 * 60 # 校验是否超时 if (current_timestamp() - user.last_active_time) < timeout_threshold: return {"code": 403, "msg": "当前账号已在其他设备登录,禁止重复登录"} # 登录成功,更新用户状态 new_token = generate_unique_uuid() update_user( user_id = user.id, login_status = 1, current_login_token = new_token, last_active_time = current_timestamp() ) set_session("user_login_token", new_token) return {"code": 200, "msg": "登录成功"}
内容的提问来源于stack exchange,提问作者Bhanu Pratap
相关产品推荐
相关产品推荐

