sa-token 如何过滤 websocket 请求

首先来介绍一下websocket是什么

WebSocket是一种网络通信协议,提供了全双工(full-duplex)通信通道,它允许服务器和客户端之间进行双向实时通信。

在传统的HTTP协议中,通信是由客户端发起的,服务器只能在接收到客户端的请求后才能发送响应。而在WebSocket协议中,服务器也可以主动向客户端发送数据。

讲人话就是这个东西可以让客户端用户端主动发消息收消息,不用像传统模式一样一问一答,必须一个开头,一个收到才能回复,直接说话唠磕不管听没听着

然后唠啥磕呢,能发送文本也能发送二进制

协议是ws,如果有加密那就是wss

使用场景有消息推送,实时聊天,在线游戏,实时传送数据等

说完优点呢 来唠唠缺点是啥

兼容: 虽然说大部分浏览器都支持这个协议,但是一些旧的还是不支持.

不支持自动重连: 如果WebSocket断开了,不能自动重连,你得在代码中设置心跳检测.

安全:虽然说能加密支持wss,但是这个协议相比https还是不够成熟,例如不支持CSRF防护,你的代码得自己处理

sa-token框架呢 肥肠好用 功能太多 各位客官想了解请移步Sa-Token官方文档

然后来唠唠这两天我遇到的坑

因为后端用的sa-token框架嘛

然后前端用WebSocket api访问准备连接的时候 是这样

**

一看 这么简单 就发呗

后端新建个类表示WebSocket的访问端点

ws://localhost:8690/mode1-api/v1/model/1

然后连接不上 查看后端log

报错: sa-token报错 未读到token

一看 又明白了 不就是sa-token配置类中没给这个网站设置过滤嘛

后来一想 不对 这不是过滤http的吗 ws的能管住?

试试呗

结果这个接口死活过不去,考察原因就是sa-token只会过滤http的

那么就想办法解决呗

去sa-token官网文档(上面有标明网站)寻找解决方法,了解到github上在该框架下有个对接WebSocket的小demo,我直接狂喜,心里想那应该按照这个一步步来肯定就完成了,

结果上面标注了

前端:

BaseUrl = localhost:8690/mode1-api/v1/model/;

this.ws = new WebSocket(BaseUrl ,[getToken()]);

后端:

@ServerEndpoint(value = "/model/socket/{satoken}"

意思就是后面跟上token 然后调用getLoginIdByToken()方法去获得token

这个方法内部封装了又调用了方法 getTokenValueNotCut()

那这么说 看来是没错啊 那为什么过不去呢 请求的时候也带了请求头啊

然后就继续翻阅文档,居然有一个重大发现,嘿您猜怎么着,

上文说的WebSocket前端调用的api中,请求的时候会将请求头替换为他自己的子协议

我直接无语?这是什么操作

那怎么办

没关系 直接修改sa-token获取tokenValue的方法逻辑

我直接就是新建一个自定义类继承 StpLogicJwtForSimple 重写 getTokenValueNotCut()方法

好的 那这算是过了sa-token过滤器链了

这时下一个问题就涌上来了

连接上立马断开

这又是Why? 我又迷了

求助友友们得知,前端请求的时候 WebSocket的api自己会带一个Sec-WebSocket-Protocol子协议,放在请求头中作为key,将传的参数作为vaule,后端发消息的时候也需要带一个一样的子协议返回去

解决办法:

唉 弄完还不行 还得给你的WebSocket配置好

只需加个参数将你的配置类传进去即可

这样就能连接WebSocket 前后端"无差别攻击" 正常聊天了

前端连接成功后,后端会发送给前端一个连接成功,调用一下静态方法

那这时 我就想将service层的数据在连接成功时一并发送给前端 我管他收到没收到呢(开玩笑,前后端还得紧密配合才能将程序做好 哈哈)

因为加了@Component注解 spring启动类@ComponentScan又可以扫描到(如果启动类放在和main包同一级别则可以不加该注解,自动扫描该包与其子包下的所有类)

我就@Autowired将业务层接口自动注入进来调用方法传个默认参数发送msg给前端就行了

然后这时重启项目 前端调用api连接 后端这时报错了 撂挑子不干了

报错空指针 自动注入对象为null 我直接一个666

为啥有组件注解为什么不能自动注入业务层接口呢

后来查资料才晓得

在Spring框架中,使用@Component注解的类会被Spring自动扫描并实例化,然后放入Spring的ApplicationContext中,这样就可以在其他地方通过自动装配(@Autowired)来使用这个类的实例

但是!!!!!

对于@ServerEndpoint注解的WebSocket类,情况有些不同。虽然你在WebSocketConnect类上使用了@Component注解,但是每次有新的WebSocket连接时,都会创建一个新的WebSocketConnect实例,而不是使用Spring容器中的单例。这是因为WebSocket的生命周期(连接打开、消息接收、连接关闭)是由WebSocket容器管理的,而不是Spring容器

就是虽然有了注解 该@ServerEndpoint注解类的生命周期也不归Spring容器管 还挺牛不让管 人家自己容器去进行创建,销毁等操作

那得了还是老老实实新建个组件类继承ApplicationContextAware去getBean()去吧

这样在 IService service = SpringContextUtils.getBean(IService .class); service.方法即可调用发送成功 格式不对记得发送之前先转

到此就是我(小白)遇到的问题了 感谢各位大佬观看

1 打赏
打赏 1 积分后可见