WebSocket握手认证

3 人关注

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

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

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

我尝试了多种方法来设置Angular 6应用程序中的cookies,例如。

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。

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

Cloudfront行为被设置为传递所有的cookies。

请告知可能的原因是什么。

angular
cookies
websocket
amazon-cloudfront
user1935987
user1935987
发布于 2018-07-30
1 个回答
user1935987
user1935987
发布于 2018-07-31
已采纳
0 人赞同

解决方案。

在我的案例中,我无法设置cookie,但我根据这个话题做了一个解决方案。 Websockets 客户端 API 中的 HTTP 头信息

关于如何用jwt令牌验证WebSocket客户端API,有很多零散的信息。这里是完整的解决方案,对 django 2.0.6 channels 2.1.1 angular 6 栈有效。

django中间件。

class TokenAuthMiddleware:
    def __init__(self, inner):
        self.inner = inner
    def __call__(self, scope):
        auth_header = None
        if 'subprotocols' in scope:
                auth_header = scope['subprotocols'][1]
            except:
        if auth_header:
                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'
            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