EventSource/SSE(服务器发送事件)- 安全 [英] EventSource / SSE (Server-Sent-Events) - Security

查看:74
本文介绍了EventSource/SSE(服务器发送事件)- 安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我关注了

如何防止知道 channelName 的用户接收服务器的所有事件流?

由于目前前端和后端托管在同一个域中,但这可能会改变,所以我需要一个广泛的答案.

解决方案

这取决于您如何设置 SSE 服务器以及您是否正在寻找经过身份验证的用户.您需要使用 Go 的 http.Handler

配置您的回显服务器以处理身份验证

一旦你这样做了,那么无论你知道频道名称和服务器,后端仍然可以拒绝向没有令牌的用户发送消息.不要将其视为用于创建频道的令牌,而是将其视为需要订阅的请求 - 然后根据请求是否经过身份验证,服务将允许或拒绝.推送服务应针对所有订阅请求持续执行此操作.

服务器是在身份验证时向令牌发出的问题,一旦您收到密钥,您就可以通过将令牌附加为名为key"的查询字符串参数来让服务器知道您已注册,或者您可以提供一个您的请求中的标头.方法如下:

var key ='xVLyHw.HSvCPg:d1RaNTqnY3s4EZZh';var url ='https://realtime.ably.io/event-stream?channels=myChannel&v=1.1&key=' + key;var eventSource = new EventSource(url);eventSource.onmessage = 函数(事件){var message = JSON.parse(event.data);console.log('Message:' + message.name + ' - ' + message.data);};

示例取自:https://www.ably.io/documentation/sse

您还可以接收一个身份验证令牌,您可以将其传递到您的accessToken"查询字符串中 - 类似于您在上面的示例中使用密钥的方式.但是请注意,您可以直接复制并将此密钥提供给那里的任何人,然后他们就可以收听同一频道.您还可以将身份验证令牌保存到 localstorage 中,并将其作为标头传递.您可以使用此库来实现此目的:

var EventSource = EventSourcePolyfill;const eventSource = new EventSource(`blabla:3000/sse?channel=myProject${projectID}`,{标题:{'Authorization': 'my secret jwt token'//或 localStorage.getItem("myToken")}});

可在此处找到用于添加标题的库:https://github.com/Yaffle/EventSource

或者您可以使用可以生成cookie的基本身份验证,并通过设置withCredentials = true将订阅请求与cookie一起发送:

var source = new EventSource(`blabla:3000/sse?channel=myProject${projectID}`, { withCredentials: true });

I followed This Thread, but I as I have not fully understood the answer in my case, I would like to post again.

I am using EventSource in my Front-End and the Backend is using echo event to stream data relatively to a drone to my application.

var source = new EventSource(`blabla:3000/sse?channel=myProject${projectID}`);
source.addEventListener(`myDrone${droneID}`, function(e){
    console.log('Received an update message:', e.data);
});

In the backend, by default nothing is streaming, and a user on connection will request to the backend to start emitting events. This call is secured using jwt_token. So to make the server start stream, a token is needed.

The question I have is, when a server is already streaming.

Let's say I am a not connected (so no valid token), and I decided to connect to the SSE stream because I know the channel name and the server is already streaming. If I start a new EventSource on blabla:3000/sse?channel=myProject${projectID}. Would I still be able to see all of the message sent trough this channel? I believe that yes.

How is it possible to secure those event streamed to be only on registered user ?

Ex : (read from top to bottom)

How can I prevent a user that know the channelName to receive all the event stream by the server ?

Since the front end and backend are hosted on the same domain at the moment, but this might change, so I need a broad answer.

解决方案

It depends on how you set up your SSE server and whether or not you're looking for authenticated users. You'd need to configure your echo server to handle authentication by using Go's http.Handler

Once you do that, then doesn't matter if you know the channel name and the server, the backend can still reject sending messages to users without tokens. Don't think of it as a token as what is used to create a channel, rather think of it as a request to subscribe is what's needed - and then depending on whether the request is authenticated or not, the service will then either allow or reject. The push service should be continuously doing this for all subscription requests.

The server is what issues to the token upon authentication, and once you receive your key, you can let the server know that you've registered by appending the token as a querystring parameter named "key", or you can provide a header within your request. Here's how:

var key ='xVLyHw.HSvCPg:d1RaNTqnY3s4EZZh';
var url ='https://realtime.ably.io/event-stream?channels=myChannel&v=1.1&key=' + key;
var eventSource = new EventSource(url);

eventSource.onmessage = function(event) {
  var message = JSON.parse(event.data);
  console.log('Message: ' + message.name + ' - ' + message.data);
};

example taken from: https://www.ably.io/documentation/sse

You can also receive an auth token, and you can pass that into your "accessToken" querystring - similar to how you do it with the key in the above example. But mind you, you can literally copy and give this key to anyone out there, and then they can listen to the same channel. You can also save the auth token into localstorage, and pass it as a header. You can use this library to achieve this:

var EventSource = EventSourcePolyfill; 
const eventSource = new EventSource(`blabla:3000/sse?channel=myProject${projectID}`,{
  headers: {
    'Authorization': 'my secret jwt token' // or localStorage.getItem("myToken")
  }
});

Library for added headers is found here: https://github.com/Yaffle/EventSource

Or you can use the basic auth that can generate a cookie, and send the request to subscribe along with the cookie by setting withCredentials = true:

var source = new EventSource(`blabla:3000/sse?channel=myProject${projectID}`, { withCredentials: true });

这篇关于EventSource/SSE(服务器发送事件)- 安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆