WebSocket握手身份验证

时间:2018-07-29 21:17:10

标签: angular cookies websocket amazon-cloudfront

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

Angular 6应用程序使用websocket功能。 本地一切正常,但是部署Angular 6应用程序后无法通过websocket握手请求传递cookie。 (仅通过cookie对websoket连接进行授权。这样做的原因并不重要。)

位于子域“ api.site.com”上的Websocket服务器

我尝试了多种方法来在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应用程序在域site.com下运行(=> api是子域)

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

请告知可能是什么原因。

1 个答案:

答案 0 :(得分: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]);