Websockets 到本地主机在基于铬的浏览器中失败
Websockets to localhost fails in chromium based browsers
我正在尝试构建一个使用 vue.js
作为前端并使用 django
作为后端的聊天网站。它在 Firefox
中工作正常,但在 MS edge
和 Google Chrome
中,Websocket 失败。我在浏览器控制台中收到此消息。
WebSocket connection to 'ws://127.0.0.1:8000/inbox/' failed
我使用 django-channels
所以在 python 控制台中打印
WebSocket CONNECT /inbox/ [127.0.0.1:4965]
WebSocket DISCONNECT /inbox/ [127.0.0.1:4965]
当我打印出错误代码时,我得到 1006
Close Code 1006 is a special code that means the connection was closed
abnormally (locally) by the browser implementation.
我的WebSocket代码
new WebSocket(url, authToken) // I use sec-websocket-protocol to transfer the authentication token
我哪里做错了还是浏览器有问题?
-- 已更新
new WebSocket("ws://127.0.0.1:8000/inbox/", "authtoken");
所以,我在第二个 Websocket 协议中发送身份验证令牌,并在后端使用中间件对用户进行身份验证。
当我删除该协议并在后端接受未经身份验证的用户时 ->
new WebSocket("ws://127.0.0.1:8000/inbox/");
-> WebSocket 连接正常。问题是在发送第二个 Websocket 协议时。
我将 'Token' 作为子协议添加到 WebSocket 和 authToken 中。然后在后端,我用相同的子协议名称接受了它:
我的 Websocket
new WebSocket(url, ["Token", authToken]) // Sending 'Token' and authToken as subprotocols
令牌授权中间件
from asgiref.sync import sync_to_async
from django.contrib.auth.models import AnonymousUser
from rest_framework.authtoken.models import Token
@sync_to_async
def get_user(headers):
try:
token_key = headers[b"sec-websocket-protocol"].decode().split(', ')[1]
token = Token.objects.get(key=token_key)
return token.user
except Token.DoesNotExist:
return AnonymousUser()
class TokenAuthMiddleware:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
headers = dict(scope["headers"])
if b"sec-websocket-protocol" in headers:
scope['user'] = await get_user(headers)
return await self.app(scope, receive, send)
Consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
class Consumer(AsyncWebsocketConsumer):
async def connect(self):
self.user = self.scope['user']
if self.user.is_authenticated:
self.room_name = await self.get_user_id(self.user)
self.room_group_name = self.room_name
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
await self.accept('Token') # Here I'm giving a subprotocol to the self.accept function
else:
await self.close()
我正在尝试构建一个使用 vue.js
作为前端并使用 django
作为后端的聊天网站。它在 Firefox
中工作正常,但在 MS edge
和 Google Chrome
中,Websocket 失败。我在浏览器控制台中收到此消息。
WebSocket connection to 'ws://127.0.0.1:8000/inbox/' failed
我使用 django-channels
所以在 python 控制台中打印
WebSocket CONNECT /inbox/ [127.0.0.1:4965]
WebSocket DISCONNECT /inbox/ [127.0.0.1:4965]
当我打印出错误代码时,我得到 1006
Close Code 1006 is a special code that means the connection was closed abnormally (locally) by the browser implementation.
我的WebSocket代码
new WebSocket(url, authToken) // I use sec-websocket-protocol to transfer the authentication token
我哪里做错了还是浏览器有问题?
-- 已更新
new WebSocket("ws://127.0.0.1:8000/inbox/", "authtoken");
所以,我在第二个 Websocket 协议中发送身份验证令牌,并在后端使用中间件对用户进行身份验证。 当我删除该协议并在后端接受未经身份验证的用户时 ->
new WebSocket("ws://127.0.0.1:8000/inbox/");
-> WebSocket 连接正常。问题是在发送第二个 Websocket 协议时。
我将 'Token' 作为子协议添加到 WebSocket 和 authToken 中。然后在后端,我用相同的子协议名称接受了它:
我的 Websocket
new WebSocket(url, ["Token", authToken]) // Sending 'Token' and authToken as subprotocols
令牌授权中间件
from asgiref.sync import sync_to_async
from django.contrib.auth.models import AnonymousUser
from rest_framework.authtoken.models import Token
@sync_to_async
def get_user(headers):
try:
token_key = headers[b"sec-websocket-protocol"].decode().split(', ')[1]
token = Token.objects.get(key=token_key)
return token.user
except Token.DoesNotExist:
return AnonymousUser()
class TokenAuthMiddleware:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
headers = dict(scope["headers"])
if b"sec-websocket-protocol" in headers:
scope['user'] = await get_user(headers)
return await self.app(scope, receive, send)
Consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
class Consumer(AsyncWebsocketConsumer):
async def connect(self):
self.user = self.scope['user']
if self.user.is_authenticated:
self.room_name = await self.get_user_id(self.user)
self.room_group_name = self.room_name
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
await self.accept('Token') # Here I'm giving a subprotocol to the self.accept function
else:
await self.close()