EventSource / SSE (отправленные сервером) - безопасность

Я прочитал спецификацию w3 @ http://www.w3.org/TR/eventsource/ о том, как работает EventSource / SSE, но я не могу найти никакой хорошей информации о том, как следует создавать частный поток.

По сути, я хочу создать способ отправки личных данных определенным пользовательским сеансам. Обе идеи ниже, кажется, делают то, что я хочу, но я не уверен, насколько они безопасны.

Пример; Каждый ли браузер, подключающийся к одному и тому же URL-адресу EventSource, получает одни и те же данные, и браузер отслеживает, какое имя события ему нужно?

var source = new EventSource('/stream');
source.addEventListener('l0ngr4nd0mSessionID', function(e){
    console.log('Received a private message:', e.data);
});

Сможет ли кто-нибудь без имени события l0ngr4nd0mSessionID получить это сообщение?

А как насчет этого дела?

var source = new EventSource('/stream/l0ngr4nd0mSessionID ');
source.addEventListener('private', function(e){
    console.log('Received a private message:', e.data);
});

Эти примеры так же хороши, как установка опции withCredentials? Мой sse-сервер - это отдельный сервер, а не основной веб-сервер, поэтому я бы предпочел не отправлять данные аутентификации с помощью withCredentials и использовать один из примеров.


person xeor    schedule 02.12.2013    source источник


Ответы (1)


Каждый поток частный. SSE не является широковещательной технологией (если вы специально не реализуете ее как таковую). Вместо этого каждому клиенту браузера предоставляется выделенное соединение сокета с вашим сервером. Ваш сервер будет использовать параллельный обработчик событий для работы только с этим клиентом и будет выбирать, какую информацию он хочет отправить этому клиенту. Вы также получаете файлы cookie этого клиента, поэтому можете идентифицировать его сеанс, а также работает базовая аутентификация.

Все становится намного сложнее, когда задействуется CORS, то есть если ваш SSE-сервер не совпадает с тем, откуда был отправлен HTML. Это та ситуация, которую вы описали. Ваш сервер должен отправить обратно "Access-Control-Allow-Origin: *", но вам не нужно использовать withCredentials, если вы хотите отправить этот уникальный идентификатор сеанса. Но учтите, что вы не получите файлы cookie или базовые данные аутентификации.

Возвращаясь к вашему вопросу, первый пример плохой. Это означает, что ваш сервер транслирует личные данные всем клиентам. Это не только проблема конфиденциальности, но и ужасная трата пропускной способности.

Ваш второй подход лучше: вы используете что-то в URL-адресе для идентификации данных, которые должен получить пользователь, вместо использования cookie или аутентификации. Обратите внимание, что любой, кто знает этот URL, может получить те же данные. SSL не поможет. Я предполагаю, что ваш идентификатор сеанса - это то, что они получают при входе на ваш основной веб-сайт, и что он истекает, когда они выходят из системы. Для большинства ситуаций я думаю, что это достаточно хорошо: хакеру придется пойти на довольно много проблем из-за относительно короткого окна доступа. Другими словами, проще использовать социальную инженерию, чтобы получить данные аутентификации пользователя. Но вам необходимо провести собственную оценку соотношения риск / польза.

Самый безопасный подход - использовать SSL с файлами cookie или базовую аутентификацию. Это просто, если веб-сервер и сервер потоковой передачи имеют одинаковое происхождение; в противном случае вам нужно использовать withCredentials.

person Darren Cook    schedule 03.12.2013
comment
Спасибо за информативный ответ. Я предпочитаю не использовать №2, потому что он попадет в журналы веб / прокси, которые регистрируют запрашивающий URL. Но вы говорите, что №1 небезопасен, и все, кто слушает / stream, могут технически видеть данные? В этом случае остается только с Credentials .. Все использует SSL .. - person xeor; 03.12.2013
comment
Да, №1 - неправильное понимание того, как работает SSE: сервер никогда не видит слушателя событий, который вы слушаете. Единственная возможность передать информацию серверу - это первоначальный запрос. Также вы не можете отправлять данные POST, поэтому они всегда попадают в журналы сервера. (Ну, вы можете настроить журналы сервера, чтобы не регистрировать это, но, как вы говорите, это не распространяется на прокси.) - person Darren Cook; 03.12.2013
comment
Я знаю, что сервер не знает, что слушают. Но сервер может знать, когда на какой r4nd0mID отправлять. Я не понимаю, как сервер может, используя что-то вроде sse.add_message("private", 'abc'), отправить личное сообщение пользователю. Если задуматься, наверное, для этого и нужны каналы SSE? Например, в github.com/niwibe/django-sse, они имеют представление о каналах. Но я видел это в стандарте SSE. - person xeor; 03.12.2013
comment
хм, неважно. Последний комментарий был глупым пуканием, и я неправильно подумал. Правильный способ - это отклонение от курса: 1) Проверка аутентификации 2) Просто отправьте данные, которые нужны конкретному идентификатору. Поскольку SSE не является широковещательным решением (о чем я думал в начале, и вы сказали), это сработает и будет безопасный. - person xeor; 03.12.2013
comment
Вы уверены насчет выделенной части темы? Кажется, что многие веб-фреймворки могут обрабатывать больше потоковых подключений, чем машина может открывать выделенные потоки на несколько порядков. См. Эликсир + феникс, весна + флюс + сетка и т. Д. - person nurettin; 27.12.2018
comment
@nurettin Ключевым моментом является выделенный сокет для каждого клиента. Если язык / фреймворк предлагает поддержку для их отслеживания, кроме подхода с выделенным потоком / процессом, он будет работать нормально. - person Darren Cook; 27.12.2018