Flutter如何检测同一账号在其他设备登录并自动下线当前设备
整体实现思路
该功能需要后端服务与Flutter端协同实现,核心逻辑是限制同一账号的有效登录会话数量,新会话生成后旧会话自动失效,前端感知到会话失效后触发登出流程即可。
第一步:后端侧改造(必填前提)
- 登录逻辑新增会话管理:用户登录成功生成
access_token/session_id时,绑定当前设备唯一标识(Flutter端可通过device_info_plus库获取后传给后端)、登录时间戳 - 配置单设备登录规则:新登录请求校验通过后,直接删除或标记失效该用户名下所有其他历史会话
- 所有鉴权接口新增有效性校验:如果请求携带的token已失效,统一返回401状态码,可自定义错误码比如
10001专门标记「会话已在其他设备登录」的场景 - 可选优化:如果需要实时触发旧设备登出,后端可集成WebSocket推送能力,新设备登录成功后向旧设备的长连接推送
session_expired事件
第二步:Flutter端实现
可根据业务对实时性的要求选择以下两种方案:
方案1:接口校验触发(无实时要求首选,实现成本最低)
- 封装全局网络请求拦截器(用Dio的话可直接添加Interceptor),统一处理所有接口响应:
当接口返回401且错误码为10001时,直接执行全局登出逻辑:清空本地存储的用户信息、token,跳转到登录页,弹出提示您的账号已在其他设备登录,当前设备已自动登出 - 新增应用前台唤醒校验:应用从后台回到前台时,主动调用一次用户信息查询接口,主动校验当前会话是否有效,避免用户长期停留在应用内不发请求,无法感知会话失效的问题
方案2:WebSocket实时推送(需要秒级触发登出时使用)
- 登录成功后建立和后端的WebSocket长连接,定期发送心跳保持连接存活
- 监听服务端推送的事件,收到
session_expired事件时,直接触发和方案1一致的全局登出逻辑即可 - 补充长连接断连重连逻辑,重连时携带当前token,后端校验如果token已失效直接返回失效事件
关键代码示例(Dio拦截器实现)
import 'package:dio/dio.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; // 替换为你项目中封装的全局路由、用户状态工具类 import 'global.dart'; class AuthInterceptor extends Interceptor { @override void onResponse(Response response, ResponseInterceptorHandler handler) { // 匹配账号在其他设备登录的场景 if (response.statusCode == 401 && response.data['code'] == 10001) { // 清空本地存储的用户数据、token Global.clearUserAuthInfo(); // 跳转登录页并清空路由栈 Global.navigatorKey.currentState?.pushNamedAndRemoveUntil('/login', (route) => false); EasyLoading.showInfo("您的账号已在其他设备登录"); return; } super.onResponse(response, handler); } @override void onError(DioError err, ErrorInterceptorHandler handler) { if (err.response?.statusCode == 401 && err.response?.data['code'] == 10001) { Global.clearUserAuthInfo(); Global.navigatorKey.currentState?.pushNamedAndRemoveUntil('/login', (route) => false); EasyLoading.showInfo("您的账号已在其他设备登录"); return; } super.onError(err, handler); } }
内容的提问来源于stack exchange,提问作者Arslan Kaleem
相关产品推荐
相关产品推荐

