问题
I want to develop real time chat with channels and these are my needs:
- PHP backend to manage site
- Redis as session and data primary storage
- Pub/Sub to send messages only to channel's interested users
- one WebSocket connection with which the messages will be send and received.
- (optional) NodeJS to use great npm packages like timesync or socket.io
I see two different architectures to achieve this:
with Socket.io
with Crossbar.io
These are my questions:
- Which architecture I should choose and why?
- The key is the user id cannot be obtained from client, because it can be malformed. So in the first architecture I think on every socket message I should attach PHPSESSID value from cookie and on sever-side retrieve PHP session from Redis. Am I right or there is better way to get user id?
- I wonder if getting user id in second architecture can be done differently?
Edit:
I choosed Crossbar.io, cause it is very powerful and allows to communicate many different language applications in real time. After studying examples, I come up with this:
On every login user have generated secret key in database.
PHP client (Thruway) connect to Crossbar server and register custom WAMP-CRA authenticator
User's browser connect to Crossbar server and is challenged. Secret and auth_id (user id) are loaded from DB with page load, so it can accomplish challenge and send response.
PHP authenticator search in DB for user with provided secret and id equal to auth_id. If there is, then it successfully authenticate session. Now we can trust that auth_id is real user id.
These are my question:
How I can get auth_id on subscribe?
I also added cookie authentication and browser is remembered after authentication. But when I look in Chrome DevTools there is any cookie nor value in local storage. Even after clearing cache my browser is still remember by Crossbar. I wonder how it is possible?
Edit2:
Maybe I was misunderstood, but the main question was choosing appropriate architecture and getting trusted user id. There was no attention so I awarded bounty and after that I was downvoted. I read a lot about real-time apps and finally decided to use Crossbar.io, so I edited question to be related to it. Then people started upvoting, proposing another architectures, but not really answering my questions. After all I managed to do it myself and presented my answer.
回答1:
About getting user id:
Every real-time chat examples which I saw, was getting id from client. It is unsafe, because client easily can manipulate it, so I needed to find another method. After reading WAMP specs I finally figured out that I have to authenticate user not only in app, but also in Crossbar.io. I choosed the dynamic WAMP-CRA method and implemented as following:
- PHP app connect to Crossbar server and register custom authenticator (similar to example)
- After user login in app there is generated secret key for him and saved in database. After logout, key is destroyed.
Workflow:
Every loaded page contain user id and secret key loaded from db:
<script> auth_id = '<?php echo $user->id ?>'; secret_key = '<?php echo $user->secret_key ?>'; </script>
- User browser connect to Crossbar.io server and get response with challenge from custom authenticator.
- It calculate signature using key and send along with auth_id to Crossbar.io server
- Authenticator gets from DB secret for provided auth_id and calculate signature. Then signatures are compared and if they are equal then authentication is successfull.
- Now auth_id contain user id and we can trust its value. Now you can refer section 'How I can get auth_id on subscribe?'.
Answers:
How I can get auth_id on subscribe?
By default publishers and subscribers does not have any knowledge about each other, but documentation show there is option to change it by configuring disclosure of caller identity. Then you can get auth_id from callback details:
PHP:
$onEvent = function ($args, $argsKw, $details, $publicationId) use ($session) { $auth_id = $details->publisher_authid; ... } $session->register('com.example.event', $onEvent);
JS:
function on_event(args, kwargs, details) { auth_id = details['publisher_authid']; ... } session.subscribe('com.example.event', on_event);
I also added cookie authentication and browser is remembered after authentication. But when I look in Chrome DevTools there is any cookie nor value in local storage. Even after clearing cache my browser is still remember by Crossbar. I wonder how it is possible?
First of all, clearing cache and hard reload does not remove cookies. When I was asking this question there was any cookie presented, but today I can see cbtid
:

回答2:
I deeply light Streamer which is used by NASA to forward truck loads of data per second.The most reliable server for real-time messaging. Power web, mobile, tablet, desktop, and IoT apps.
Optimized data streaming for web and mobile. Lightstreamer enables several forms of real-time messaging. It is flexible enough to be used in any scenario, including mission critical applications. ► Real-time Data Push and Web Sockets ► In-App Messaging and Push Notifications ► Pub-sub with fan-out broadcasting and one-to-one messaging ► Firewall and proxy friendly ► Adaptive bandwidth throttling
As for your first question to get the auth_id on subscription , just monitor connection subscriptions then store tier upon successful connection. Also cookies are not recommended , use jwt.JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.Authentication is one of the big parts of every application. Security is always something that is changing and evolving.JWT helps you solve that concern.Since it is stateless.
回答3:
PHP Ratchet is one of the best implementations I've used for real-time communications via WebSockets. Its based on ZMQ Sockets which is used in several online gaming applications and chat applications.
The following examples will get you started pretty quick and will answer your questions around auth_id and subscriptions:
http://socketo.me/docs/hello-world
http://socketo.me/docs/push
Overview of the Architecture:
http://socketo.me/docs/push#networkarchitecture
I would advice creating individual connections(toppics) per conversation as it doesn't really take a hit on performance and will add an additional layer of security per chat.
来源:https://stackoverflow.com/questions/42666799/real-time-chat-in-php-redis-pub-sub-websockets-nodejs