Websocket, Angular 2 and JSON Web token Authentication

后端 未结 3 2107
死守一世寂寞
死守一世寂寞 2021-01-31 18:58

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

  • User logs in:
  • Server returns JSON Web Token (JWT) abc123...
  • <
相关标签:
3条回答
  • 2021-01-31 19:15

    I settled on the following protocol:

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

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

    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. Client opens the websocket, sending the ticket in query param

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

    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){/*...*/}
    
    0 讨论(0)
  • 2021-01-31 19:18

    Client opens the websocket, sending the UserName and Password in query param

    ws://<username>:<password>@<ip-address><path>
    

    Example: new $WebSocket('ws://user:123456@127.0.0.0/util')

    0 讨论(0)
  • 2021-01-31 19:30

    Use djangorestframework-jwt to generated your JWTs, and the following Django-Channels 2 middleware.

    The token can be set via the djangorestframework-jwt http APIs, and it will also be sent for WebSocket connections if JWT_AUTH_COOKIE is defined.

    settings.py

    JWT_AUTH = {
        'JWT_AUTH_COOKIE': 'JWT',     # the cookie will also be sent on WebSocket connections
    }
    

    routing.py:

    from channels.routing import ProtocolTypeRouter, URLRouter
    from django.urls import path
    from json_token_auth import JsonTokenAuthMiddlewareStack
    from yourapp.consumers import SocketCostumer
    
    application = ProtocolTypeRouter({
        "websocket": JsonTokenAuthMiddlewareStack(
            URLRouter([
                path("socket/", SocketCostumer),
            ]),
        ),
    
    })
    

    json_token_auth.py

    from http import cookies
    
    from channels.auth import AuthMiddlewareStack
    from django.contrib.auth.models import AnonymousUser
    from django.db import close_old_connections
    from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
    
    
    class JsonWebTokenAuthenticationFromScope(BaseJSONWebTokenAuthentication):
        """
        Extracts the JWT from a channel scope (instead of an http request)
        """
    
        def get_jwt_value(self, scope):
            try:
                cookie = next(x for x in scope['headers'] if x[0].decode('utf-8') == 'cookie')[1].decode('utf-8')
                return cookies.SimpleCookie(cookie)['JWT'].value
            except:
                return None
    
    
    class JsonTokenAuthMiddleware(BaseJSONWebTokenAuthentication):
        """
        Token authorization middleware for Django Channels 2
        """
    
        def __init__(self, inner):
            self.inner = inner
    
        def __call__(self, scope):
    
            try:
                # Close old database connections to prevent usage of timed out connections
                close_old_connections()
    
                user, jwt_value = JsonWebTokenAuthenticationFromScope().authenticate(scope)
                scope['user'] = user
            except:
                scope['user'] = AnonymousUser()
    
            return self.inner(scope)
    
    
    def JsonTokenAuthMiddlewareStack(inner):
        return JsonTokenAuthMiddleware(AuthMiddlewareStack(inner))
    
    
    0 讨论(0)
提交回复
热议问题