Websocket,Angular 2和JSON Web令牌认证 [英] Websocket, Angular 2 and JSON Web token Authentication

查看:101
本文介绍了Websocket,Angular 2和JSON Web令牌认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Angular 2应用程序(用打字稿编码)具有简单的身份验证方案:

My Angular 2 app (coded in typescript) has a simple authentication scheme:

  • 用户登录:
  • 服务器返回JSON Web令牌(JWT)abc123...
  • 在每次API调用中,应用程序都会在Authorization标头中发送JWT
  • 服务器验证JWT并授予访问权限
  • User logs in:
  • Server returns JSON Web Token (JWT) abc123...
  • On every API call, the app sends the JWT in the Authorization header
  • Server validates the JWT and grants access

现在,我想添加websocket.我想知道如何在那里验证用户.由于我无法控制将哪些标头发送到Websocket服务器(WS),因此无法发送JWT.

Now I'd like to add websockets. I'm wondering how to authenticate the user there. Since I don't control which headers are sent to the websocket server (WS), I cannot send the JWT.

到目前为止,我的想法(尚未实现)

My idea so far (not yet implemented):

  • 客户端打开websocket:let sock = new WebSocket('wss://example.com/channel/');
  • WS服务器接受握手,但不进行任何身份验证检查.在此阶段可以使用标准的HTTP标头.
  • 客户端在套接字上侦听open事件.插座打开后:
    • 客户端使用type='auth' payload='JWT_VALUE'
    • 发送消息
    • Client opens websocket: let sock = new WebSocket('wss://example.com/channel/');
    • WS server accepts the handshake without any authentication check. Standard HTTP headers are available at this stage.
    • Client listens to the open event on the socket. Once the socket is open:
      • client sends a message with type='auth' payload='JWT_VALUE'
      • 如果验证失败,则服务器断开套接字
      • 如果没有isAuthenticated的客户端发送任何其他类型的消息,则服务器将断开套接字的连接
      • If validation fails, server disconnects the socket
      • If a client without isAuthenticated sends any other type of message, server disconnects the socket

      2个问题:服务器资源可以由连接但从未发送JWT的客户端占用,并且更清洁的解决方案将在客户端未经身份验证的情况下阻止握手.

      2 problems: server resources can be taken up by clients who connect but never send the JWT, and a cleaner solution would block the handshake if the client is not authenticated.

      其他想法:

      • 客户端可以在以下路径中发送JWT:new WebSocket('wss://example.com/channel/<JWT>/')
        • pro:此信息在握手期间可用
        • con:该路径似乎不是JWT的适当"位置.特别是因为中间代理和访问日志将保存路径;在设计HTTP API时,我已经决定不在URL中包含JWT
        • pro:此信息可能在握手过程中可用(不确定IP)
        • con:对于"猜测"来说,当客户端从来没有展示过JWT时,应该将客户端与JWT关联起来似乎是非常不安全的.例如,这将意味着,欺骗受害人的UA并使用相同网络(代理,公共wifi,大学Intranet等)的某人将能够冒充受害人.
        • pro: this info may be available during the handshake (not sure about IP)
        • con: it seems horribly insecure to "guess" that a client should be associated with a JWT when the client never presented it in the first place. It would mean for instance that someone who spoofs the victim's UA and uses the same network (proxy, public wifi, university intranet...) will be able to impersonate the victim.

        您如何在websockets上对客户端进行身份验证?假设用户已经通过HTTP登录,并且Angular 2应用具有JWT令牌.

        How do you authenticate clients on websockets? Assume the user already logged in via HTTP and that the Angular 2 app has a JWT token.

        推荐答案

        我选择了以下协议:

        1..客户端登录到站点并接收身份验证令牌(JSON Web令牌)

        1. Client logs into the site and receives an authentication token (JSON Web Token)

        GET /auth
        {
            user: 'maggie',
            pwd:  'secret'
        }
        
        // response
        { token: '4ad42f...' }
        

        2..经过身份验证的客户端请求Websocket连接凭单

        2. Authenticated client requests a websocket connection ticket

        GET /ws_ticket
        Authorization: Bearer 4ad42f...
        
        // response: single-use ticket (will only pass validation once)
        { ticket: 'd76a55...', expires: 1475406042 }
        

        3..客户端打开Websocket,在查询参数中发送故障单

        3. Client opens the websocket, sending the ticket in query param

        var socket = new WebSocket('wss://example.com/channel/?ticket=d76a55...');
        

        4..然后,Websocket服务器(PHP)会在接受握手之前验证票证

        4. Websocket server (PHP) then validates the ticket before accepting the handshake

        /**
        * Receives the URL used to connect to websocket. Return true to admit user,
        * false to reject the connection
        */
        function acceptConnection($url){
            $params = parse_str(parse_url($url, PHP_URL_QUERY));
            return validateTicket($params['ticket']);
        }
        
        /** Returns true if ticket is valid, never-used, and not expired. */
        function validateTicket($ticket){/*...*/}
        

        这篇关于Websocket,Angular 2和JSON Web令牌认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆