Подтвердить что ты не робот

Сервер Websocket: как авторизировать клиентов?

В настоящее время я создаю веб-страницу с игрой с использованием холста html5 и веб-узлов. У меня есть сервер websocket, написанный на Perl, запущенный на сервере: 3000. На сервере я также установил apache и создал веб-сайт, который пользователь может посетить: http://server/. javascript на этой странице создает websocket для ws://server: 3000

Соединение работает, и я могу отправлять сообщения из своего браузера и получать ответы, все показанные в div на данный момент. Сообщения, которые я отправляю, на данный момент являются только "message:...", поэтому сервер знает, что это сообщение и выводит "..." всем пользователям, которые в настоящее время подключены к "игре".

Теперь проблема заключается в том, что любой может написать свой собственный клиент, который будет подключаться к ws://server: 3000 и отправлять/получать соответствующие сообщения. Таким образом, они будут использовать мой backend, но не мой клиент (я бы хотел, чтобы они играли только из http://server/).

Как я могу убедиться, что используется только мой клиент? Главная проблема - обманывать. Вы можете написать бота, который подключается к порту и играет за вас, отправив сообщения и проиндексируя те, которые он получает... Как преодолеть эту проблему?

4b9b3361

Ответ 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.
Вы также можете ознакомиться с исходным кодом своих клиентских библиотек.