Сервер Websocket: как авторизировать клиентов?
В настоящее время я создаю веб-страницу с игрой с использованием холста html5 и веб-узлов. У меня есть сервер websocket, написанный на Perl, запущенный на сервере: 3000. На сервере я также установил apache и создал веб-сайт, который пользователь может посетить: http://server/. javascript на этой странице создает websocket для ws://server: 3000
Соединение работает, и я могу отправлять сообщения из своего браузера и получать ответы, все показанные в div на данный момент. Сообщения, которые я отправляю, на данный момент являются только "message:...", поэтому сервер знает, что это сообщение и выводит "..." всем пользователям, которые в настоящее время подключены к "игре".
Теперь проблема заключается в том, что любой может написать свой собственный клиент, который будет подключаться к ws://server: 3000 и отправлять/получать соответствующие сообщения. Таким образом, они будут использовать мой backend, но не мой клиент (я бы хотел, чтобы они играли только из http://server/).
Как я могу убедиться, что используется только мой клиент? Главная проблема - обманывать. Вы можете написать бота, который подключается к порту и играет за вас, отправив сообщения и проиндексируя те, которые он получает... Как преодолеть эту проблему?
Ответы
Ответ 1
Я использую веб-сервер Jetty.
Я использую Basic authorization. Сначала я использовал это просто потому, что его было легко реализовать. Однако, после обнаружения проблемы с авторизацией, представленной в websockets, я думаю, что основная авторизация - хороший механизм для использования.
Заголовок запроса обновления содержит данные авторизации:
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Authorization:Basic YWRtaW46cm9vdA==
Cache-Control:no-cache
Connection:Upgrade
На моем сервере websocket с каждым событием OnMessage я вызываю:
session.getUpgradeRequest().getUserPrincipal()
Затем я могу использовать эту информацию, чтобы решить, разрешено ли обрабатывать данные. Кроме того, я проверяю происхождение сокета в событии OnConnect:
session.getUpgradeRequest().getOrigin()
Ответ 2
То, о чем вы просите, невозможно достичь. Вы можете предпринять шаги, чтобы сделать третью сторону неавторизованным клиентом, но в конце концов, если третья сторона может использовать вашего законного клиента, они всегда могут посмотреть, что она делает, и скопировать ее. вы ничего не можете сделать, чтобы остановить это.
Есть вещи, которые вы можете сделать, чтобы сделать это сложнее:
- Предоставьте ваш клиент как запутанный, зашифрованный javascript.
- Используйте шифрование, чтобы сообщения, которые вы отправляете и получаете через интерфейс websocket, затрудняют интерпретацию случайного хакера.
Но даже если вы это сделаете, определенный злоумышленник может расшифровать и дефобучить ваш javascript, найти ключ, который вы используете для шифрования сообщений, а затем вернуть их в обычный текст и реконструировать то, что они делают.
Ответ 3
Характер сети таков, что такая вещь становится проще (для хакеров) и сложнее для тех, кто строит приложения/веб-сайты. Обычно вы используете "referer", чтобы убедиться, что запрос поступает с вашего сайта/домена. Это не безупречное доказательство, но работает в большинстве случаев.
В Html 5 Я знаю, что гиперссылки не должны отправлять рефери. Это может измениться и на включение веб-узлов и т.д.
Даже если вы должны зашифровать ваше сообщение солью какого-то типа и отправить хэш этого сообщения вместе с вашим сообщением для проверки сообщения против хэша на сервере, ваш код на стороне клиента потенциально доступен и доступен любому, они могут взломать вашу логику.
Спецификация WebSocket была постоянным потоком. Некоторые браузеры либо отключили, либо удалили поддержку WebSocket.
Протокол квитирования WebSocket (с использованием Sec-WebSocket-Key1 и Sec-WebSocket-Key2) должен был сделать вещи более безопасными, но эта спецификация не будет работать через большинство прокси-серверов. Вы можете прочитать спецификацию здесь
http://www.whatwg.org/specs/web-socket-protocol/
Обратите внимание, что протокол рукопожатия был введен для совершенно другой цели. Это не то, что вам нужно, а скорее, чтобы не допустить, чтобы клиент взломал сервер таким образом, что, если сервер не отвечает рукопожатием, клиент не может связаться с сервером. Но в вашем случае вам нужно будет ответить рукопожатием, не зная клиента.
Поэтому я не думаю, что есть надежный способ сделать то, что вам нужно.
Ответ 4
Выполняйте логин/аутентификацию обычным способом, а затем укажите идентификатор сеанса в запросе обновления веб-сокета.
Ответ 5
Я пришел к той же проблеме. Я пишу websocket- > socket proxy, чтобы сделать клиент HTML5 для нашей JAVA/Flash-игры. Они используют самодельное шифрование на этапе авторизации, чтобы убедиться, что это устаревший клиент.
Я не думаю, что безопасно вставлять один и тот же код шифрования, когда открыты источники js файла. Пока я спрятал этот алгоритм auth в своем WS-прокси, но мне нужно как-то обнаружить несанкционированные клиенты WS сейчас:)
Я использую временные идентификаторы сеансов с веб-сайта, чтобы проверить, разрешен ли веб-сайт клиенту на веб-сайте. Однако это ненадежно.
Также я думаю о каком-то механизме, чтобы клиент (браузер) загружал динамически созданный файл javascript, запускал его и отправлял серверу websocket, который может проверить действительный результат. Таким образом, я могу быть уверен, что клиент - браузер (или сложный бот с JS-движком:)). Во всяком случае, это только мои мысли, и мне кажется, что это сложно реализовать, я еще не пытался это сделать.
Ответ 6
Очень просто, я думаю, добавьте заголовок в соединение websocket, пусть это будет имя хоста или что-то еще, и назначьте ему какое-то загадочное значение, и проверьте это критическое значение каждый раз, когда соединение с веб-сервером выполняется против ваших серверов webscoket.
Ответ 7
Я предлагаю вам посмотреть, как это делают другие службы.
См. Например pusher.com, в частности частные каналы, которые они используют.
Подробнее об их протоколе можно узнать на http://pusher.com/docs/pusher_protocol.
Вы также можете ознакомиться с исходным кодом своих клиентских библиотек.