Всем привет, у меня почему-то именно на удаленном сервере(ubuntu 20) пользователь в self.scope, является анонимом. Сам я на винде
consumers.py
class CallConsumer(AsyncWebsocketConsumer):
"""
WebSocket-потребитель для отправки уведомлений пользователям.
"""
async def connect(self) -> None:
"""Устанавливает соединение и проверяет юзера на аутентификацию"""
self.user = self.scope["user"]
print(self.scope)
self.group_name = 'notifications'
await self.channel_layer.group_add(
self.group_name,
self.channel_name
)
await self.accept()
print('connected ws')
async def disconnect(self, close_code) -> None:
"""Отключает соединение"""
await self.channel_layer.group_discard(
self.group_name,
self.channel_name)
async def send_notification(self, event: dict) -> None:
""" Отправляет уведомление конкретному пользователю"""
print(self.scope['user'])
if self.scope['user'].id == int(event['data'][
'employee_number']): # сравниваем id текущего пользователя со списком из контекста(send_simple_notification)
await self.send(text_data=json.dumps(event['data'], ensure_ascii=False))
asgi.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from apps.middleware import TokenAuthMiddleware
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cpm.settings")
django_asgi_app = get_asgi_application()
from apps.call.urls import websocket_urlpatterns
application = ProtocolTypeRouter(
{
"http": django_asgi_app,
"websocket": TokenAuthMiddleware(URLRouter(websocket_urlpatterns))
}
)
TokenAuthMiddleware - это самописный класс, который берет jwt токен из query params и аунтифицирует пользователя
TokenAuthMiddleware
from urllib.parse import parse_qs
from channels.db import database_sync_to_async
import jwt
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser
from django.utils.translation import gettext_lazy as _
from rest_framework.exceptions import AuthenticationFailed
from rest_framework_simplejwt.authentication import JWTTokenUserAuthentication
from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
from rest_framework_simplejwt.tokens import UntypedToken
from cpm import settings
User = get_user_model()
class SimpleJWTAuthentication:
"""
Simple JWT token based authentication.
Clients should authenticate by passing the token in the Authorization header.
For example:
Authorization: Bearer <token>
"""
def __init__(self):
self.jwt_auth = JWTTokenUserAuthentication()
def authenticate(self, token):
user = self.get_user_from_token(token)
if not user or not user.is_active:
return AnonymousUser(), None
return user
def get_user_from_token(self, token):
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.SIMPLE_JWT['ALGORITHM']])
user_id = payload['user_id']
return User.objects.get(id=user_id)
except jwt.ExpiredSignatureError:
raise AuthenticationFailed(_("Token has expired."))
except jwt.InvalidTokenError:
raise AuthenticationFailed(_("Invalid token."))
except User.DoesNotExist:
return None
@database_sync_to_async
def get_user(scope):
"""
Return the user model instance associated with the given scope.
If no user is retrieved, return an instance of `AnonymousUser`.
"""
# postpone model import to avoid ImproperlyConfigured error before Django
# setup is complete.
from django.contrib.auth.models import AnonymousUser
if "token" not in scope:
raise ValueError(
"Cannot find token in scope. You should wrap your consumer in "
"TokenAuthMiddleware."
)
token = scope["token"]
user = None
try:
auth = SimpleJWTAuthentication()
user = auth.authenticate(token)
except AuthenticationFailed:
pass
return user or AnonymousUser()
class TokenAuthMiddleware:
"""
Custom middleware that takes a token from the query string and authenticates via
JWT tokens.
"""
def __init__(self, app):
# Store the ASGI application we were passed
self.app = app
async def __call__(self, scope, receive, send):
token = parse_qs(scope["query_string"].decode("utf8"))["token"][0]
try:
# This will automatically validate the token and raise an error if token is invalid
UntypedToken(token)
except (InvalidToken, TokenError) as e:
# Token is invalid
print(e)
return None
else:
decoded_data = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
print(decoded_data)
scope["token"] = token
scope["user"] = await get_user(scope)
return await self.app(scope, receive, send)
urls
websocket_urlpatterns = [
path(r"ws/notifications/", CallConsumer.as_asgi()),
]
js код для открытия ws
const token = "токен";
const socket1 = new WebSocket(`wss://${window.location.host}/ws/notifications/?token=${token}`);
socket1.addEventListener('open', (event) => {
console.log('WebSocket connection opened:', event);
console.log('Открыто');
// Теперь, когда соединение открыто, вы можете отправлять сообщения на сервер
// Например, отправка сообщения для запроса уведомлений
// Запускаем метод receive
});
// Обработка события получения сообщения от сервера
socket1.addEventListener('message', (event) => {
console.log('Received message from server:', event.data);
// Здесь вы можете обработать полученное сообщение
});
// Обработка события закрытия соединения
socket1.addEventListener('close', (event) => {
console.log('WebSocket connection closed:', event);
});
// Обработка события ошибки
socket1.addEventListener('error', (event) => {
console.error('WebSocket error:', event);
});
терминал:
(<django.contrib.auth.models.AnonymousUser object at 0x7fb2e0d93790>, None)
Я перезапускаю сервер, генерирую токен jwt, вставляю его в js код, но пользователь все равно аноним. На локалке такой проблемы нет, какие есть варианты решения?