简体   繁体   English

EventSource / SSE(服务器发送事件)- 安全

[英]EventSource / SSE (Server-Sent-Events) - Security

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.我在前端使用 EventSource,后端使用echo事件将相对于无人机的数据流式传输到我的应用程序。

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 .此调用使用jwt_token进行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.假设我没有连接(所以没有有效的令牌),我决定连接到 SSE 流,因为我知道频道名称并且服务器已经在流式传输。 If I start a new EventSource on blabla:3000/sse?channel=myProject${projectID} .如果我在blabla:3000/sse?channel=myProject${projectID}上启动一个新的 EventSource 。 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 ?如何防止知道 channelName 的用户接收服务器的所有事件流?

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.这取决于您如何设置 SSE 服务器以及您是否正在寻找经过身份验证的用户。 You'd need to configure your echo server to handle authentication by using Go's http.Handler您需要使用 Go 的 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.服务器是在身份验证时向令牌发出的问题,一旦您收到您的密钥,您可以通过将令牌附加为名为“key”的查询字符串参数来让服务器知道您已注册,或者您可以在您的要求。 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示例取自: 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.您还可以接收一个身份验证令牌,您可以将其传递到您的“accessToken”查询字符串中 - 类似于您在上面的示例中使用密钥的方式。 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.您还可以将身份验证令牌保存到 localstorage 中,并将其作为标头传递。 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添加标题的库可在此处找到: 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:或者,您可以使用可以生成 cookie 的基本身份验证,并通过设置 withCredentials = true 将订阅请求与 cookie 一起发送:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM