html5 - servidor - websocket php
Servidor websocket: ¿Cómo autorizar a los clientes? (9)
Como han dicho otros, no podrá hacer cumplir que solo su propio código del lado del cliente habla con su websocket. Sin embargo, puede vincular las conexiones de websocket con el resto de su servidor web.
Por ejemplo, suponga que autentica a sus jugadores a través de un formulario de inicio de sesión servido por su servidor web. Luego, al iniciar sesión correctamente, genera un token que le entrega al cliente y le pide a su código de cliente que lo pase como un parámetro de consulta con el que puede verificar en su controlador de conexión websocket:
- el usuario publica el nombre de usuario / contraseña en
http://server/play
- generar un token aleatorio, ponerlo en una base de datos como
(token, username, timestamp)
- genera y sirve un documento HTML que carga el código Javascript de tu juego y pasa este token (por ejemplo, el cuerpo contiene
myGame.start(<literaltoken>)
- el Javascript de tu juego se conecta a
ws://server:3000/?token=<token>
- su servidor busca el token y puede vincular la conexión con el usuario y / o rechazar la conexión si el token no se conoce o es demasiado antiguo
Si desea evitar tener que mantener el lado del servidor en el estado, podría hacer que el token sea un blob (username, timestamp)
de (username, timestamp)
cifrado y firmado, usando alguna clave secreta del lado del servidor, y descifrar / verificar ese blob en el controlador de websocket.
Actualmente estoy creando una página web con un juego que utiliza lienzo html5 y websockets. Tengo un servidor websocket escrito en perl que se ejecuta en el servidor: 3000. En el servidor también instalé Apache e hice un sitio web que el usuario puede visitar: http://server/ . javascript en esta página crea un websocket para ws: // server: 3000
La conexión funciona y puedo enviar mensajes desde mi navegador y obtener las respuestas, todo lo que se muestra en un div por ahora. Los mensajes que envío son por ahora solo "mensaje: ...", por lo que el servidor sabe que es un mensaje y envía "..." a todos los usuarios conectados actualmente al "juego".
Ahora el problema es que cualquiera podría escribir su propio cliente que se conectaría a ws: // server: 3000 y enviaría o recibiría los mensajes apropiados. De esta manera usarían mi backend, pero no mi cliente (me gustaría que solo jueguen desde http://server/ ).
¿Cómo puedo asegurarme de que solo se use mi cliente? La principal preocupación es hacer trampa. Podría escribir un bot que se conecte a un puerto y juegue para usted enviando mensajes e interpretando los que recibe ... ¿Cómo superar este problema?
Estoy usando un servidor web Jetty.
Estoy usando la autorización básica. Usé esto al principio simplemente porque era fácil de implementar. Sin embargo, después de descubrir el problema de autorización presentado por websockets, creo que la autorización básica es un buen mecanismo para usar.
El encabezado de solicitud de actualización tiene datos de autorización con hash:
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
En mi servidor websocket, con cada evento OnMessage que llamo:
session.getUpgradeRequest().getUserPrincipal()
Luego, puedo usar esta información para decidir si los datos están autorizados para ser procesados. Además, verifico el origen del socket en el evento OnConnect:
session.getUpgradeRequest().getOrigin()
Inicie sesión / autenticación de la forma habitual e incluya el identificador de sesión en la solicitud de actualización de socket web.
La naturaleza de la web es tal que este tipo de cosas se vuelven más fáciles (para los hackers) y más difíciles para aquellos que construyen aplicaciones / sitios web. Normalmente, usaría "referer" para asegurarse de que la solicitud proviene de su sitio / dominio. No es infalible, pero funciona para la mayoría de los casos.
En Html 5 sé que los hipervínculos no tienen que enviar el remitente. Eso podría cambiar para incluir websockets y similares también.
Incluso si tuviera que cifrar su mensaje con algún tipo de sal y enviar el hash junto con su mensaje para validar el mensaje contra el hash en el servidor, su código del lado del cliente está potencialmente disponible y es visible para cualquier persona para que pueda descifrarlo. tu logica
La especificación de WebSocket ha sido de flujo constante. Algunos navegadores han deshabilitado o eliminado su soporte WebSocket por el momento.
Se suponía que el protocolo de intercambio de WebSocket (usando Sec-WebSocket-Key1 y Sec-WebSocket-Key2) hacía las cosas más seguras, pero esta especificación no funcionará en la mayoría de los servidores proxy. Puede leer la especificación aquí http://www.whatwg.org/specs/web-socket-protocol/
Tenga en cuenta que el protocolo de protocolo de enlace fue introducido para un propósito muy diferente. Eso no es lo que está buscando, sino más bien evitar que un cliente piratee un servidor de tal manera que, a menos que el servidor responda con un apretón de manos, el cliente no puede comunicarse con el servidor. Pero en su caso, tendrá que responder con un apretón de manos sin conocer al cliente.
Así que no creo que haya una manera confiable de hacer lo que necesita.
Lo que estás pidiendo es imposible de lograr. Puede tomar medidas para dificultar que un tercero haga un cliente no autorizado, pero al final, siempre que el tercero pueda usar su cliente legítimo, siempre puede ver lo que hace y copiarlo, y hay nada que puedas hacer para detener eso.
Sin embargo, hay cosas que puedes hacer para que sea más difícil:
- Entregue a su cliente como javascript cifrado y ofuscado.
- Utilice el cifrado para hacer que los hackers informales no puedan interpretar los mensajes que envía y recibe a través de su interfaz websocket.
Pero incluso si lo hace, un atacante determinado puede descifrar y desofigurar su javascript, encontrar la clave que está usando para cifrar los mensajes y luego revertirlos a texto sin formato y aplicar ingeniería inversa a lo que hacen.
Propongo que eche un vistazo a cómo otros servicios hacen esto. Vea por ejemplo pusher.com , específicamente los canales privados que usan.
Puede obtener más información sobre su protocolo en http://pusher.com/docs/pusher_protocol .
También puede consultar el código fuente de las bibliotecas de sus clientes .
Supongo que muy simple: agregue un encabezado en websocket connect, deje que sea el nombre de host o algo así, y asígnele un valor críptico, y verifique este valor críptico cada vez que se realice una conexión websocket en sus servidores webscoket.
Vine al mismo problema. Estoy escribiendo websocket-> socket proxy para hacer cliente HTML5 para nuestro juego JAVA / Flash. Utilizan el cifrado hecho a sí mismo en la etapa de autorización para asegurarse de que sea un cliente heredado.
No creo que sea seguro insertar el mismo código de encriptación ya que las fuentes del archivo js están abiertas. Por ahora escondí ese algoritmo de autenticación en mi proxy WS, pero ahora necesito detectar clientes WS no autorizados :)
Estoy usando identificadores de sesión temporales del sitio web para verificar si un cliente de websocket está autorizado en el sitio web. Aunque no es confiable.
También estoy pensando en algún mecanismo para hacer que un cliente (navegador) descargue un archivo javascript generado dinámicamente, lo ejecute y lo envíe al servidor websocket, que puede verificar el resultado válido. De esa manera puedo estar seguro de que el cliente es el navegador (o un robot complicado con el motor JS :)). De todos modos, eso son solo mis pensamientos y parece difícil de implementar, no lo intenté todavía.
La autenticación básica funciona como se indica en esta respuesta aquí: encabezados HTTP en la API del cliente Websockets
Con Basic Auth puede incluir el nombre de usuario y la contraseña en la URL:
ws://username:password@localhost:8888/
Alternativamente, puede implementar su propia seguridad simplemente enviando contraseñas de hash / md5 / sha1 a través del protocolo y un nombre de usuario o algún otro identificador de sesión. Por supuesto, es bueno tener una solicitud de token antes de que todo lo que el cliente también deja pasar.