什么是 SSE?
SSE(Server-Sent Events)指的是服务器主动向浏览器推送数据的一种技术,也称作 "服务器推送"。与传统的客户端轮询方式不同,SSE 是服务器通过不断向浏览器推送最新的数据,而不是客户端不断向服务器请求数据。这样做不仅可以降低服务端资源消耗,也能比传统轮询的方式能够更快地推送数据给客户端。
SSE 由 3 部分组成:
- HTTP 头信息:Content-Type,如下:
Content-Type: text/event-stream
- 事件类型:即消息的类型,如下:
event: login status
- 数据内容:消息内容,可包含多行数据,如下:
data: {"username": "张三", "loginTime": "2022-01-01 10:00:00"}
其中,以 event:
开头的行是事件类型,可以省略。以 data:
开头的行是数据内容,每个 SSE 消息可以包含多个数据内容行。
SSE 遇到 XSS 怎么办?
SSE 对于跨站攻击 (XSS) 是极其敏感的,因为 SSE 在传输数据的过程中,对 HTML 标记和 JavaScript 代码没有做任何过滤,因此存在被注入脚本的风险。这些恶意脚本可以用来攻击用户浏览器或发送用户 cookie 到攻击者的服务器。
为了避免 XSS 攻击,我们需要对 SSE 消息中的数据进行过滤和转义。以下是一些建议:
1. 数据转义
发送 SSE 消息到浏览器前,务必对数据进行转义。我们建议使用成熟的第三方库来完成数据转义,比如 jQuery 的 $.fn.text()
、Lodash 的 _.escape()
等方法。
const data = {username: "<script>alert('恶意代码')</script>"} const message = `data: ${JSON.stringify(data)}\n\n`; sendToBrowser(_.escape(message));
2. 防止注入 event 字段
event 字段可以控制浏览器的事件,容易被攻击者利用。因此,最好把 SSE 的 event 字段隔离起来,避免 js 代码被执行。
const event = "user-login"; const data = {username: "user"}; // 不需要对 data 字段进行转义,因为它不是放在 HTML 标签里的 const message = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
3. 只允许特定的域名来访问
在浏览器端,我们可以使用 Server-Sent Events API 创建一个 SSE 连接,并向一个特定的服务器发送请求。而攻击者则可以轻松模拟这个请求。因此,只允许特定域名的请求能够访问我们的 SSE API,非法请求将被拒绝。
-- -------------------- ---- ------- ----- --------- - --------------------------- --------------------------- -- -------------------------------------------- - ----------------------- - ------------------------------ ----------------------- -- ------ --------------- -------------------- ---------------- ----------- --- -- -- --- -- -
总结
SSE 对于服务器推送技术来说,是一种非常高效和稳定的方案,但它也存在诸多风险,特别是在面对跨站攻击时。为了保障 SSE 的稳定性和安全性,我们必须采取适当的措施。在编写 SSE 代码时,请务必注意遵守上述安全建议,并选择合适的第三方库,以确保代码的有效性和安全性。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6483a83d48841e98942f94d1