如何通过 Django Channels 将 cookie 添加到标头?
Posted
技术标签:
【中文标题】如何通过 Django Channels 将 cookie 添加到标头?【英文标题】:How to add cookie to header through Django Channels? 【发布时间】:2019-04-26 21:35:53 【问题描述】:在我的前端,我有以下配置。身份验证是手动的,因为 react native 在持久会话时失败:
...
const authLink = setContext(request =>
storage.getCookie().then(cookie => (
// Before the request is sent: set cookie header
headers:
cookie,
,
credentials: 'omit', // set cookies manually
))
)
const setTokenLink = new ApolloLink((operation, forward) =>
// Send the request to the server
return forward(operation).map(response =>
// After response is returned: store cookie in local storage
const context = operation.getContext()
const
response: headers ,
= context
if (headers)
storage.setCookie(headers.get('set-cookie'))
return response
)
)
storage.getCookie().then(cookie => console.log(cookie))
// console.log('cookie', storage.getCookie().then(cookie => cookie))
const httpLink = createUploadLink(
uri: `$domainApi/graphql/`,
)
const wsClient = new SubscriptionClient(
domainWs,
lazy: true,
reconnect: true,
connectionParams:
authToken: storage.getCookie(),
,
)
)
...
但这似乎会影响 websockets,因为在后端,标头不包含 cookie。
class GraphqlSubcriptionConsumer(SyncConsumer):
def __init__(self, scope):
super().__init__(scope)
self.subscriptions =
self.groups =
def websocket_connect(self, message):
self.send("type": "websocket.accept", "subprotocol": "graphql-ws")
def websocket_disconnect(self, message):
for group in self.groups.keys():
group_discard = async_to_sync(self.channel_layer.group_discard)
group_discard(f"django.group", self.channel_name)
self.send("type": "websocket.close", "code": 1000)
raise StopConsumer()
def websocket_receive(self, message):
request = json.loads(message["text"])
id = request.get("id")
if request["type"] == "connection_init":
return
elif request["type"] == "start":
print("scope user:", self.scope["user"]) //returns AnonymousUser
print("scope headers:", self.scope["headers"]) //returns headers without the cookie
...
有了这个配置,我得到了
'type': 'websocket.receive', 'text': '"type":"connection_init","payload":"authToken":"_40":0,"_65":1,"_55":"sessionid=bci028bzn1cgxyuynvb7fjevc5ynqdil","_72":null'
在第一条类型为connection_init
的消息中。所以我想知道是否有办法手动将 django 中的 cookie(可能在 if request["type"] == "connection_init":
内)插入作用域,以便start
类型的后续消息包含 cookie。
任何小提示/提示都会有所帮助。
【问题讨论】:
【参考方案1】:在服务器的握手响应中设置 cookie(使用 channels==2.3.1
测试):
def connect(self): # connect method of your WebsocketConsumer
# called on connection
headers =
headers['Set-Cookie'] = 'myCookie=myValue'
self.accept(subprotocol=(None, headers))
一旦建立连接,就无法通过Set-Cookie
HTTP 响应标头从服务器向用户代理发送 cookie。那是因为它是一个开放的 TCP 套接字,协议不再是 HTTP。
Django Channels
在后台使用autobahn
。 https://github.com/crossbario/autobahn-python/blob/9e68328df3c23ca3eee67017404235024f265693/autobahn/websocket/types.py#L285
【讨论】:
以上是关于如何通过 Django Channels 将 cookie 添加到标头?的主要内容,如果未能解决你的问题,请参考以下文章
Django使用Channels实现WebSocket--下篇
如何从 Django Channels Web 套接字数据包中获取当前用户?