Почему мое WebSocket-соединение отклоняется с сообщением «Unauthenticated user» в Django Channels даже при наличии действительного JWT-токена?
Я работаю над приложением для чата в реальном времени, используя Django Channels и WebSockets. Я реализовал пользовательскую систему аутентификации пользователей с помощью JWT-токенов и подключил аутентификацию на основе токенов к WebSocket-соединению с помощью промежуточного ПО Django Channels. Однако мое WebSocket-соединение постоянно отклоняется с сообщением: "Unauthenticated user attempted to connect."
, несмотря на отправку действительного JWT-токена в заголовке Authorization
.
Вот соответствующий код и настройки для моего проекта:
Настройка проекта:
- Django Версия: 4.1.4
- Django Channels Version: 4.0.0
- ASGI Server: Daphne
- Пользовательская модель:
BasicUserProfile
(которая хранит токен JWT в полеauth_token
)
Код:
1. CustomAuthMiddleware
- Middleware для аутентификации JWT:
import jwt
from datetime import datetime
from channels.middleware.base import BaseMiddleware
from authentication.models import BasicUserProfile
from django.contrib.auth.models import AnonymousUser
from django.conf import settings
from channels.db import database_sync_to_async
class CustomAuthMiddleware(BaseMiddleware):
async def populate_scope(self, scope):
user = scope.get('user', None)
if user is None:
token = self.get_token_from_headers(scope)
if token:
user = await self.get_user_by_token(token)
else:
user = AnonymousUser()
scope['user'] = user
def get_token_from_headers(self, scope):
headers = dict(scope.get('headers', []))
token = headers.get(b'authorization', None)
if token:
token_str = token.decode()
if token_str.startswith("Bearer "):
return token_str[len("Bearer "):]
return None
@database_sync_to_async
def get_user_by_token(self, token):
try:
decoded_token = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
if decoded_token.get('exp') and decoded_token['exp'] < datetime.utcnow().timestamp():
return AnonymousUser()
user_profile = BasicUserProfile.objects.get(auth_token=token)
return user_profile.user
except (jwt.ExpiredSignatureError, jwt.DecodeError, BasicUserProfile.DoesNotExist):
return AnonymousUser()
2. ChatConsumer
- WebSocket Consumer:
Проблема:
Несмотря на реализацию аутентификации на основе JWT через промежуточное ПО, соединение WebSocket всегда отклоняется с сообщением:
"Unauthenticated user attempted to connect."
.
Я отправляю JWT-токен как Bearer
-токен в Authorization
заголовке WebSocket-запроса, но соединение не проходит успешную аутентификацию.
Что я пробовал:
- Убедитесь, что токен правильно передается в заголовке.
- Проверили, что
CustomAuthMiddleware
правильно декодирует JWT и получает пользователя. - Убедились, что JWT корректно работает для API-запросов (вне WebSocket).
- Отладили промежуточное ПО, чтобы убедиться, что токен принимается и декодируется.
Ожидаемое поведение:
Соединение WebSocket должно правильно аутентифицировать пользователя с помощью токена JWT и позволить ему подключиться и общаться с другими пользователями в режиме реального времени.
Вопрос:
Что может заставить WebSocket отклонить соединение с сообщением "Unauthenticated user attempted to connect."
, несмотря на то, что в заголовке отправлен действительный JWT-токен? Есть ли проблема в том, как я обрабатываю аутентификацию токена для WebSockets в Django Channels, или есть что-то еще, что я могу упустить?