2021年7月7日星期三

Netty 通道怎么区分对应的用户?

作者:南城之南

出处:https://www.cnblogs.com/liangshu/p/12459657.html

前言

考虑一个功能业务,在web程序中向指定的某个用户进行实时通讯

在Web运用的Socket通讯功能中(如在线客服),为保证点对点通讯.而这个看似简单的根据用户寻到起channel通道实际会碰到不少问题

  1. web程序中的Http协议是无状态的
  2. 一般项目中socket服务和web项目是独立部署的
  3. socket连接存在重连的情况,而Channel对象每次都不一样
  4. Channel是面向网卡绑定的,无法序列化

解决方案

通过管理一个线程安全的用户标识(如用户主键)和对应channelmap链表

private final ConcurrentHashMap<String, Channel> channelMap = new ConcurrentHashMap<>();

那么问题来了,

  • netty模块中怎么得到这个用户标识?
  • 又如何保证netty socket模块可以安全的识别某个通道属于某个用户?(这个可以像上面一样的方式解决)
  • netty socket模块接收到一条消息又任何证明这条通道是可信的?

netty的实现中是没有认证也没有HttpSession这个东西的,也就是说.在netty程序线程中是无法得到web项目登录的用户情况的.

出于这点,参考web项目集群的session共享方案.可以在Redis等缓存中保存登录信息.

  1. web项目中登录之后在redis中在这个以用户id为名的key中保存一个token,
  2. 在客户端socket通道建立之后立马发送包含一个用户标识ASKsocket服务端,
  3. 服务端根据ASK计算一个tokenredis比对.一旦比对成功,则绑定当前channel和用户之间的关系;
  4. 之后server每接收到一条消息就检测当前通道有没有绑定用户信息

这个key一次性的.这点非常重要,试想一下.在你前台项目可能因为cookie过期或者后台已经自动将该用户下线,而你的用户标识ASK暴露.那么就可能被恶意连接发送消息;

另外关于tokenASK之类的验证传输如果仅仅是为了识别和绑定用户与channel的关系,这点也是可以忽略的,只要redis中保存该用户的登录状态即可,通道建立的第一次通讯就传输当前浏览器的登录用户标识,再去redis中比对即可,但是redis中的这个key还是一次性的好,避免一个用户建立多条socket通道

正确的绑定通道Channel和用户之间的关系

如果我们仅仅有一个ConcurrentHashMap<String, Channel>,是无法快速优雅的判断当前channel是属于哪个用户的;我看到别人绝大多数的实现是在创建一个channelId用户标识的Map来管理

//key为channel的长id,channel.id().asLongText();value为用户idprivate final ConcurrentHashMap<String, String> channelAndUserMap = new ConcurrentHashMap<>();

其实这不是最合理的做法,正确的做法是利用Channel对象提供的AttributeMap来保存该通道的附带信息,很多人不知道Channel对象提供了一个绑定自定义数据的Map

使用示例:

//用户id=>channel示例private final ConcurrentHashMap<String, Channel> channelMap = new ConcurrentHashMap<>();/** * 判断一个通道是否有用户在使用 * 可做信息转发时判断该通道是否合法 * @param channel * @return */public boolean hasUser(Channel channel) { AttributeKey<String> key = AttributeKey.valueOf("user"); return (channel.hasAttr(key) || channel.attr(key).get() != null);//netty移除了这个map的remove方法,这里的判断谨慎一点}/** * 上线一个用户 * * @param channel * @param userId */public void online(Channel channel, String userId) { //先判断用户是否在web系统中登录? //这部分代码个人实现,参......

原文转载:http://www.shaoqun.com/a/852337.html

跨境电商:https://www.ikjzd.com/

亚马逊全球开店:https://www.ikjzd.com/w/1299

ishare:https://www.ikjzd.com/w/2308

盘古集团:https://www.ikjzd.com/w/1448


作者:南城之南出处:https://www.cnblogs.com/liangshu/p/12459657.html前言考虑一个功能业务,在web程序中向指定的某个用户进行实时通讯在Web运用的Socket通讯功能中(如在线客服),为保证点对点通讯.而这个看似简单的根据用户寻到起channel通道实际会碰到不少问题web程序中的Http协议是无状态的一般项目中socket服务和web项目是独立部署
急速:https://www.ikjzd.com/w/1861
亚马逊低价政策暗潮涌动,卖家还有利可图吗?:https://www.ikjzd.com/articles/103918
外贸干货:揭秘WhatsApp营销的新玩法!:https://www.ikjzd.com/articles/103920
Wish蓝海产品类目分享2019(二):巴西蓝海产品类目:https://www.ikjzd.com/articles/103921
选品前看同类产品review,你真的会看吗?:https://www.ikjzd.com/articles/103922
口述公么的粗大满足了我 睡着了被偷偷滑进去了:http://lady.shaoqun.com/a/248400.html
门卫又粗又大又长好爽 被门卫老头吸得欲仙欲死:http://lady.shaoqun.com/a/247705.html
自述陪读发生了性关系 小东西早想在这办了你了:http://www.30bags.com/m/a/249961.html
有些人见300次没用,有些人见3次就够了:http://lady.shaoqun.com/a/406843.html
如何摆脱一个小小的"工具"人,成为一个"威武"的君子:http://lady.shaoqun.com/a/406844.html
如何用TikTok打响独立站,出海跨境东南亚市场?:https://www.ikjzd.com/articles/146444
3个问题解决亚马逊卖家对感谢卡/礼品券的担忧:https://www.ikjzd.com/articles/146443

没有评论:

发表评论