Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Я задавал вопрос насчет архитектуры БД, а теперь я сформулировал вопрос насчет архитектуры сервиса сообщений.
- Сервис сообщений будет полагаться на протокол wamp и на шаблон pub/sub. В обычной ситуации, когда мы отправляем запрос через http, мы отправляем запрос к серверу, сервер валидирует данные, делает что-то ещё (например сохраняет в БД) и затем отправляет ответ. Роутер wamp такое поведение не предусматривает и просто перенаправляет сообщения между клиентами.
- Значит, нужно на серверной стороне написать такой клиент, который будет подписываться на [u]все сообщения[/u], валидировать их, сохранять в БД, а затем только перенаправлять клиенту пользователя.
- Т.е. Алиса публикует сообщение по uri server.message.to.bob, сервер валидирует его и делает публикацию на client.message.to.bob.
- Ситуация очень не типична. Судя по всему, даже нельзя вернуть клиенту ошибку об [i]собственной ошибке[/i] (прим. ошибка валидации). Это совсем отлично от RESTful API. Как лучше написать архитектуру чтобы она была понятна другим разработчикам?
- Я планировал это сделать просто. Создать скрипт (который будет реквайриться сервером или отдельно через консоль как демон), который будет подписываться на все сообщения.
- Messenger.js
- var autobahn = require('autobahn');
- var connection = new autobahn.Connection({
- ...
- });
- connection.onopen = function(session) {
- session.subscribe('server.message', function(m) {
- let message = new Message(...) //серилиазируем сообщение
- message.validate(); // в случае ошибки нельзя вернуть ответ клиенту
- session.publish(`client.message.to.${message.to}`); // Ничего страшного если сделать публикацию не дожидаясь сохранения в БД, чтобы повысить скорость?
- message.save();
- }, { match: "prefix" }); //"prefix" говорит о том что нужно подписаться на все совпадения с префиксом server.message
- //Кто-то кому-то пишет
- session.subscribe('server.writing', function(w) {
- //валидируем что пользователь может вообще писать другому пользователю...
- session.publish(`client.writing.to.${w.to}`);
- }, { match: "prefix" }); //"prefix" говорит о том что нужно подписаться на все совпадение с префиксом server.message
- };
- connection.open();
- Или, я не понимаю, wamp должен только "уведомить" что кто-то отправил сообщение, а клиент должен сам сделать запрос к серверу чтобы получить сообщения? Не будет ли это слишком медленно? Мне не нравится такой подход - в чем смысл по два раза делать запрос, гонять трафик, создавать лишнюю нагрузку?
- Наверно, для такого случая конечно лучше использовать микросервисы(?) написанные на Питоне, которые можно встроить в роутер https://crossbar.io/docs/Router-Components/ а не скрипты на ноде.
- Следующий вопрос...
- Чтобы авторизовать публикации для клиентов %%напомню что они могут приходить только от сервера%%, нужно воспользоваться встроенным в роутер механизмом - функции динамической авторизации. Которая, принимает в качестве аргументов данные сессии (роль, дополнительные данные авторизации, которые предоставляются самим клиентом
- к прим. jwt), uri по которому происходит действие, и само действия (публикация или подписка) и ещё опции этого действия (пример { match: "prefix" }). В ответ эта функция должна вернуть разрешено или нет совершать это действие.
- https://crossbar.io/docs/Authorization/#dynamic-authorization
- >The method must accept three arguments: (session, uri, action, options) and must return a dict with the following keys...
- Нужно чтобы для каждого (для n-ого количества) uri и действия была своя проверка.
- К примеру,
- 1. Пользователь может только сделать публикацию на сервер
- 2. Пользователь может только подписаться на относящиеся к нему публикации с сервера
- 3. Сервер может подписаться на относящиеся к нему публикации
- 4. Сервер может публиковать для пользователей данные
- На практике, это выглядит ещё обширнее:
- def authorize(session, uri, action, options):
- if re.match('^server\.message\.to\.', uri) and action == 'publish':
- //проверяем токен и делаем всё остальное... и если всё ок - возвращаем True
- token = session['authextra']['Bearer token']
- payload = jwt.decode(token, JWT_SECRET)
- ...
- return True
- if re.match('^client\.message\.to\.', uri) and action == 'subscribe':
- //делаем тоже самое...
- if re.match('^client\.message\.to\.', uri) and action == 'publish':
- // нужно проверить что это делает именно сервер
- // для этого я решил создать jwt со свойством isServer: true
- // как ещё надёжней сделать эту проверку?
- token = session['authextra']['Bearer token']
- payload = jwt.decode(token, JWT_SECRET)
- if 'isServer' in payload and payload['isServer']:
- ...
- return True
- if re.match('^server\.writing\.to\.', uri) and action == 'publish':
- //проверяем что пользователь присутствует в системе
- ...
- return True
- //и так далее, таких проверок может быть n-ое количество
- return False // запрещаем всё во всех остальных случаях "default"
- Вопрос прост - Как вынести это n-ое количество проверок в отдельную архитектуру?
- [i]Спасибо большое...[/i]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement