1、写在前面的话

生活中,我们在使用一些APP的时候,有过一种体验,就是在A手机上登录账号,因为某些原因需要在B手机上登录,然后就会在A手机上看到类似"该账号在其他设备登录"的提示,像下面这样:

这种方式叫单设备登录,作用很明显,就是为了保护用户账号安全,今天我们不说手机APP,我们来说说PC Web网站如何简单快速实现这种效果。本篇文章重点是实现单设备登录,内容未涉及WebSocket + Redis的概念和使用方法。限于本人经验,如有错误,欢迎指正。

2、概念

简单的给”单设备登录“定义一下,就是只能在一个设备上登录,若同时在其他设备登录,先前登录的用户会被提醒:该账户在其他设备登录。例如微信,在一台手机登录中,同时拿另一台手机登录该账户,之前那部手机的账户会被挤下线。

3、思路

使用此方案的前提是要保证登录账号没有重复

在socket里面创建两个Map,sessionPool和sessionIds,分别用来存放客户端会话池和客户端会话标记

用户登录账号成功,进入应用首页,和服务端建立socket连接,将账号+"_"+UUID格式的字符串作为state参数的值

在OnOpen连接时,以state为key,当前session为value存入sessionPool,以sessionId为key,state为value存入sessionIds

以"_"分隔state成数组,取第一个元素即获取到当前登录的账号

在缓存(Redis)里模糊查询含有该账号的key集合,如果存在,那么就取出对应的value值,其实这个value存的就是首先登陆这个账号的那个state,就可以根据这个state给先登录的账号设备推送消息并做logout的操作,并清除缓存

把当前登录的state作为key和value存入缓存,失效时间设置与否都可以,如果设置的话需超过登录态失效的时长

4、代码实现

这里贴上几段核心代码

后台WebSocket-On0pen,切记如果设置缓存失效时间的话需超过登录态失效的时长

/*** 连接时触发* @param state* @param session*/
@OnOpen
public void onOpen(@PathParam(value = "state")String state,Session session) {this.session = session;sessionPool.put(state, session);sessionIds.put(session.getId(), state);     String[] arry = state.split("_");Set<String> keys = redisService.keys(arry[0] + "*");if (keys != null) {List<String> list = redisService.multiGet(keys);for (String value : list) {sendMessage("您的账号于"+ DateUtils.pageformat(DateUtils.getCurrentTime()) + "在另一台设备登录,如果这不是您的操作,那么您的登录密码已泄露,请尽快修改",value);redisService.delete(value);}}redisService.set(state,state,7200);
}/*** 自定义发送消息的方法* @param message* @param state*/
public static void sendMessage(String message,String state) {Session session = sessionPool.get(state);if (session != null) {try {session.getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();}}
}

查看缓存

前端js连接WebSocket方法

function getUUID() {return 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {var r = Math.random() * 16 | 0,v = (c === 'x' ? r : (r & 0x3 | 0x8));return v.toString(16);
});
}function loginSocket(userName) {var websocket = null;
if ('WebSocket' in window) {websocket = new WebSocket("ws://localhost:8080/mobile/socketServer/"+userName+"_"+getUUID());
} else {layer.alert('当前浏览器 不支持 websocket')
}
//连接成功建立的回调方法
websocket.onopen = function () {console.log('websocket连接成功');
};
//连接发生错误的回调方法
websocket.onerror = function () {console.log('websocket连接发生错误');
};
//接收到消息的回调方法
websocket.onmessage = function (event) {$.getJSON("logout", function(r){console.log('logout:'+event.data);});layer.confirm(event.data, {btn: ['确定'] //按钮}, function(){location.href = 'login.html';});
};
//连接关闭的回调方法
websocket.onclose = function () {console.log("websocket连接关闭");
};
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {websocket.close();
};
}

5、验证效果

打开谷歌浏览器,账号密码登录

打开火狐浏览器,模拟不同设备,账号密码登录

再看下谷歌浏览器,页面弹窗提示


点击确定会跳转到登录页,谷歌浏览器的账号已经被挤下线退出应用

谷歌浏览器再次登录,看下火狐浏览器,也弹窗提示,之前登录的账号也被挤下线退出应用



谢谢阅读

WebSocket + Redis简单快速实现Web网站单设备登录功能相关推荐

  1. [转]你会做Web上的用户登录功能吗?

    Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能后,我觉得很有必要写一篇文章教大家怎么来做用户登录功能.下面的文章告诉大家这个功能可能并没有你所想像的那么简单,这是一个关 ...

  2. 实现Web上的用户登录功能

    https://coolshell.cn/articles/5353.html Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能后,我觉得很有必要写一篇文章教大家怎么来做 ...

  3. Web上的用户登录功能安全

    转载自:http://www.daimami.com/web/217218.htm 你会做Web上的用户登录功能吗? Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能后, ...

  4. web上的用户登录功能

    Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能后,我觉得很有必要写一篇文章教大家怎么来做用户登录功能.下面 的文章告诉大家这个功能可能并没有你所想像的那么简单,这是一个 ...

  5. 你会做Web上的用户登录功能吗?

    你会做Web上的用户登录功能吗? 2011年8月25日 陈皓    Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能后,我觉得很有必要写一篇文章教大家怎么来做用户登录功能 ...

  6. Web上的用户登录功能——酷壳_陈皓

    为什么80%的码农都做不了架构师?>>>    Web上的用户登录功能应该是最基本的功能了,可是在我看过一些站点的用户登录功能后,我觉得很有必要写一篇文章教大家怎么来做用户登录功能. ...

  7. 配合OAuth2进行单设备登录拦截

    2019独角兽企业重金招聘Python工程师标准>>> 要进行单设备登录,在其他地点登录后,本地的其他操作会被拦截返回登录界面. 原理就在于要在登录时在redis中存储Session ...

  8. 网站集成QQ登录功能

    原文:网站集成QQ登录功能 最近在做一个项目时,客户要求网站能够集成QQ登录的功能,以前没做过这方面的开发,于是去QQ的开放平台官网研究了一下相关资料,经过自己的艰苦探索,终于实现了集成QQ登录的功能 ...

  9. 基于token的登录管理(多设备登录、单设备登录)

    详情参见: https://gitee.com/xxssyyyyssxx/token 不管是客户端接口还是网页H5接口,一般我们都需要登录验证,即要求所有的接口访问都必须在登录之后,以确认身份,防止非 ...

最新文章

  1. IT人的理性、激情与爱情
  2. #include NOIP2009 Junior 细胞分裂 ——using namespace wxl;
  3. 观光旅游(Floyd)
  4. 网页元素坐标表示及坐标计算方法
  5. python 示例_带有示例的Python字典update()方法
  6. c语言程序设计题2015,2015年荐C语言程序设计等级考试习题汇编.doc
  7. IDEA——Git 的设置与使用
  8. 绝对素数(信息学奥赛一本通-T1153)
  9. 搭建微信公共平台的本地测试
  10. js给php赋值,JavaScript_javascript给span标签赋值的方法,js给span标签赋值的方法?一般 - phpStudy...
  11. 1024. 科学计数法 (20)-PAT乙级真题
  12. (O)JS核心:call、apply和bind
  13. VALSE2019总结(4)-主题报告
  14. Java对Map排序
  15. 初级办公计算机,初级(计算机办公软件应用)教案
  16. 计算机网络在电力系统继电保护的应用毕业论文,毕业论文 110kV电力系统继电保护的配置...
  17. 个人总结 - JS逆向解析
  18. Freemarker数字格式化总结
  19. 思考输入变量与输出变量之间的关系---从线性回归出发
  20. 球相交的表面积并/体积并

热门文章

  1. Wireshark For Windows
  2. 计算点到直线/线段的距离
  3. 单向和双向沟通带来启发
  4. 华为防火墙配置基于源地址的策略路由
  5. python中列表(list)的基本定义和用法
  6. java 日期处理_java日期处理总结
  7. SemanticKITTI点云拼接+PCL可视化
  8. 网上预约 php,php65高校体育场地网上预约使用系统
  9. 【GitLab】GitLab数据自动删除、自动备份
  10. 前端开发中环境变量配置