【问题标题】:WebSocket handshake authenticationWebSocket 握手认证
【发布时间】:2019-01-06 03:41:22
【问题描述】:

我有一个 Angular 6 应用程序和 python(django 2.0.6) 后端。 Angular 6 应用程序使用 AWS S3 和 CloudFront 部署。

Angular 6 应用程序使用 websocket 功能。 一切都在本地运行良好,但是当部署 Angular 6 应用程序时,无法通过 websocket 握手请求传递 cookie。 (授权仅通过 cookie 用于 websoket 连接。这是有原因的,不相关。)

Websocket 服务器位于子域:`api.site.com``

我尝试了多种方法在 Angular 6 应用中设置 cookie,例如:

let domain = 'api.site.com'

document.cookie = `Token=${token}; domain=${domain}; path=/`;
document.cookie = `Token=${token}; path=/`;
document.cookie = `Token=${token};
document.cookie = `Token=${token}, domain=${domain}, path=/`;

使用ngx-cookie-service:

this.cookieService.set('Token', token, undefined, '/', 'api.site.com');
this.cookieService.set('Token', token, undefined, '/');
this.cookieService.set('Token', token);

token 是 JWT 令牌。

对于上述所有情况,在部署应用程序时,Token cookie 不会与 websocket 握手一起传递。使用wss 协议。 angular 6 app 在site.com 域下运行(=> api 是一个子域)

Cloudfront 行为设置为传递所有 cookie。

请告知可能的原因。

【问题讨论】:

    标签: angular cookies websocket amazon-cloudfront


    【解决方案1】:

    解决方案:

    在我的情况下,我无法设置 cookie,但基于此主题提出了解决方案:HTTP headers in Websockets client API

    关于如何使用 jwt 令牌对 WebSocket 客户端 API 进行身份验证有很多零散的信息。这是适用于django 2.0.6channels 2.1.1angular 6 堆栈的完整解决方案:

    django 中间件:

    class TokenAuthMiddleware:
    
        def __init__(self, inner):
            self.inner = inner
    
        def __call__(self, scope):
            auth_header = None
            if 'subprotocols' in scope:
                try:
                    auth_header = scope['subprotocols'][1]
                except:
                    pass
    
            if auth_header:
                try:
                    user_jwt = jwt.decode(
                        auth_header,
                        settings.SECRET_KEY,
                    )
                    scope['user'] = MyUser.objects.get(
                        id=user_jwt['user_id']
                    )
                    close_old_connections()
                except (InvalidSignatureError, KeyError, ExpiredSignatureError, DecodeError):
                    scope['auth_error'] = 'KeyError'
                    pass
                except Exception as e:  # NoQA
                    scope['auth_error'] = 'Unknown'
    
            return self.inner(scope)
    
    
    TokenAuthMiddlewareStack = lambda inner: TokenAuthMiddleware(AuthMiddlewareStack(inner))
    

    ws 消费者:

    class WsConsumer(JsonWebsocketConsumer):
        def connect(self):
            self.accept('auth_token')
            if self._is_authenticated():
                ***do things***
            else:
                logger.error("ws client auth error")
                self.close(code=4003)
    
        def _is_authenticated(self):
            if hasattr(self.scope['headers'], 'auth_error'):
                return False
            if type(self.scope['user']) is AnonymousUser or not self.scope['user']:
                return False
            return True
    

    WebSocket 客户端 API(js cli):

      this.socket = new WebSocket('ws://host.com/ws/`, ['auth_token', token]);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-16
      • 1970-01-01
      • 1970-01-01
      • 2015-03-16
      • 2015-01-04
      相关资源
      最近更新 更多