Почему мое соединение WebSocket отклоняется с указанием «Неаутентифицированный пользователь» в каналах Django даже при нPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Почему мое соединение WebSocket отклоняется с указанием «Неаутентифицированный пользователь» в каналах Django даже при н

Сообщение Anonymous »

Я работаю над приложением для чата в реальном времени, используя каналы Django и WebSockets. Я реализовал собственную систему аутентификации пользователей с использованием токенов JWT и подключил аутентификацию на основе токенов к соединению WebSocket с помощью промежуточного программного обеспечения Django Channels. Однако мое соединение WebSocket всегда отклоняется с сообщением: «Неаутентифицированный пользователь попытался подключиться»., несмотря на отправку действительного токена JWT в заголовке авторизации.
Вот соответствующий код и настройки для моего проекта:
Настройка проекта:
  • < li>Версия Django: 4.1.4
  • Версия каналов Django: 4.0.0
  • Сервер ASGI: Дафна
  • Пользовательская модель пользователя: BasicUserProfile (которая хранит токен JWT в поле auth_token)
Код:

1. CustomAuthMiddleware — промежуточное ПО для аутентификации 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:

Код: Выделить всё

import json
import logging
from channels.generic.websocket import AsyncWebsocketConsumer
from authentication.models import BasicUserProfile
from .models import Chat
from .serializers import ChatSerializer
from django.contrib.auth.models import AnonymousUser

logger = logging.getLogger(__name__)

class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
current_user = self.scope.get('user', None)

if current_user is None or not current_user.is_authenticated:
logger.warning("Unauthenticated user attempted to connect.")
await self.close(code=4000)
return

receiver_username = self.scope['url_route']['kwargs']['username']

try:
current_profile = await self.get_user_profile(current_user.id)
receiver_profile = await self.get_receiver_profile(receiver_username)
except BasicUserProfile.DoesNotExist:
logger.error(f"Profile not found for user {current_user.id} or receiver {receiver_username}")
await self.close(code=4001)
return

self.room_name = f'{min(current_profile.id, receiver_profile.id)}_{max(current_profile.id, receiver_profile.id)}'
self.room_group_name = f'chat_{self.room_name}'

self.sender_profile = current_profile
self.receiver_profile = receiver_profile

await self.channel_layer.group_add(self.room_group_name, self.channel_name)
await self.accept()

async def disconnect(self, close_code):
if hasattr(self, 'room_group_name'):
await self.channel_layer.group_discard(self.room_group_name, self.channel_name)
logger.debug(f"User {self.scope['user'].username} disconnected from {self.room_group_name}")

async def receive(self, text_data):
data = json.loads(text_data)
message = data.get('message', '')
sender_username = data.get('senderUsername', '')

sender_profile = await self.get_user_profile_by_username(sender_username)
if not sender_profile:
logger.error(f"Sender profile for {sender_username} not found.")
return

chat_message = await self.save_message(sender_profile, message)
chat_history = await self.get_chat_history()

await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message,
'senderUsername': sender_username,
'chat_history': chat_history,
}
)

async def chat_message(self, event):
message = event['message']
sender_username = event['senderUsername']
chat_history = event['chat_history']

await self.send(text_data=json.dumps({
'message': message,
'senderUsername': sender_username,
'chat_history':  chat_history,
}))

@database_sync_to_async
def get_user_profile(self, user_id):
return BasicUserProfile.objects.get(user__id=user_id)

@database_sync_to_async
def get_receiver_profile(self, username):
return BasicUserProfile.objects.get(user__username=username)

@database_sync_to_async
def get_user_profile_by_username(self, username):
return BasicUserProfile.objects.get(user__username=username)

@database_sync_to_async
def save_message(self, sender, message):
chat = Chat.objects.create(sender=sender, content=message, receiver=self.receiver_profile)
return chat

@database_sync_to_async
def get_chat_history(self):
chat_history_feed = Chat.objects.filter(sender=self.sender_profile, receiver=self.receiver_profile) | \
Chat.objects.filter(sender=self.receiver_profile, receiver=self.sender_profile)
chat_serializer = ChatSerializer(chat_history_feed, many=True)
return chat_serializer.data
Проблема:
Несмотря на реализацию аутентификации на основе JWT через промежуточное программное обеспечение, WebSocket соединение всегда отклоняется с сообщением:

Код: Выделить всё

"Unauthenticated user attempted to connect."
.
Я отправляю токен JWT в качестве токена носителя в заголовке Authorization запроса WebSocket, но соединение не аутентифицируется успешно.

Что я пробовал:
  • < li>Проверено, что токен правильно передается в заголовке.
  • Проверено, что CustomAuthMiddleware правильно декодирует JWT и извлекает пользователя.
  • Подтверждено, что JWT правильно работает для запросов API (вне WebSocket).< /li>
    Отлажено промежуточное программное обеспечение, чтобы гарантировать получение и декодирование токена.
Ожидаемое поведение:
Соединение WebSocket должно правильно аутентифицировать пользователя с помощью токена JWT и позволять ему подключаться и общаться с другими пользователями в реальном режиме. -time.

Вопрос:
Что может быть причиной отклонения WebSocket соединение с сообщением "Неаутентифицированный пользователь попыталась подключиться." даже несмотря на то, что в заголовке отправляется действительный токен JWT? Есть ли проблема с тем, как я обрабатываю аутентификацию токенов для WebSockets в каналах Django, или мне может не хватать чего-то еще?

Подробнее здесь: https://stackoverflow.com/questions/792 ... ser-in-dja
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»