WebSockets - correct approach for creating channel

2019-04-02 15:57发布

I have a scenario whereby I want to inform users of my site that someone has commented on an article on which they have also commented. This is a lot like the way that SO notifies me when someone responds to a question!

Server side, I persist the comment and then look up all users who commented on the same article. I then broadcast (I'm using Atmosphere):

PushContext pushContext = PushContextFactory.getDefault().getPushContext();

for(User u : users){       
    // channel name, message
    pushContext.push("/user_" + u.id, "someone commented! blah blah"); 
}

The "channel" I am broadcasting to is the user's "own" channel, since I don't want every user to be notified. I use the user's ID in the channel name to achieve this.

Is this the right way to do ensure only relevant users get notified?

I guess I also want to do two more things:

  1. Only push to users whom I believe are still online. If they aren't online, then it's a waste of resources pushing to them.
  2. Encrypt the message, because otherwise anybody could listen for my messages, if they know my user ID.

Is there anything else I need to think of?

1条回答
聊天终结者
2楼-- · 2019-04-02 16:43

SO uses WebSockets, for example when a comment is made on this posting, you get a notification in your status bar at the top left of the SO page.

When the page is loaded, the browser makes a protocol upgrade request which looks like this:

Request URL:ws://sockets-se.or.stackexchange.com/
Request Method:GET
Status Code:101 Switching Protocols
Request Headersview source
Connection:Upgrade
Cookie:__qca=P0-1697817643-1763440830313; __utma=27376923.959753990.1338240830.1353943751.1384115154.33; __utmc=27693525; __utmz=27699983.1356175156.31.31.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)
Host:sockets-se.or.stackexchange.com
Origin:http://stackoverflow.com
Sec-WebSocket-Extensions:x-webkit-deflate-frame
Sec-WebSocket-Key:6qFl45+6gZ526yMMo79zWQ==
Sec-WebSocket-Version:13
Upgrade:websocket
(Key3):00:00:00:00:00:00:00:00
Response Headersview source
Connection:Upgrade
Sec-WebSocket-Accept:B4h2G+gi78iNZZXg+o6iAztgF1I=
Upgrade:websocket
(Challenge Response):00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00

The socket is then open, and the server can send updates to the browser. For example, a notification of my comment is received by the browser as:

{"action":"1-question-12993099","data":"{\"a\":\"comment-add\",\"id\":12993099,\"commentid\":19334206,\"acctid\":1298157}"}

It doesn't contain the actual comment; it appears that this is simply used to tell the browser to show the red icon. When you then click, it makes a request to get the page, including the comment. The question ID (12993099), comment ID (19334206) and account ID (1298157) is contained in that frame.

I cannot see anything in the above which would stop some hacker creating a web socket to listen to your notifications. The cookies look to me to be Google Analytics cookies to me, or at least the second and third ones do. Perhaps the first is some code which you wouldn't know, had I not just published it (no worries, I change it!).

In your example of Atmosphere, I know that when Web Sockets does not work, it defaults to long polling, which then requests a URL with the channel name in it. So you could get the client to generate a channel name which only it would know and associate that with the logged in user. But anyone sniffing the network would again have access to your traffic, so you'd have to secure it using secure web sockets (WSS) and HTTPS (for long polling fallback).

查看更多
登录 后发表回答