您是否尝试在 django-channels 应用程序中添加中间件来对用户进行身份验证和授权,
如果不按照以下步骤操作:
1)在与 routing.py 相同的文件夹中创建一个名为 middleware.py 的新文件
2)在middleware.py中添加如下内容
Note: The following implementation is from django-channels documentation
from urllib.parse import parse_qs
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser
from django.db import close_old_connections
from channels.auth import AuthMiddleware, AuthMiddlewareStack, UserLazyObject
from channels.db import database_sync_to_async
from channels.sessions import CookieMiddleware, SessionMiddleware
from rest_framework_simplejwt.tokens import AccessToken
User = get_user_model()
"""[summary]
plucks the JWT access token from the query string and retrieves the associated user.
Once the WebSocket connection is opened, all messages can be sent and received without
verifying the user again. Closing the connection and opening it again
requires re-authorization.
for example:
ws://localhost:8000/<route>/?token=<token_of_the_user>
"""
@database_sync_to_async
def get_user(scope):
close_old_connections()
query_string = parse_qs(scope['query_string'].decode())
token = query_string.get('token')
if not token:
return AnonymousUser()
try:
access_token = AccessToken(token[0])
user = User.objects.get(id=access_token['id'])
except Exception as exception:
return AnonymousUser()
if not user.is_active:
return AnonymousUser()
return user
class TokenAuthMiddleware(AuthMiddleware):
async def resolve_scope(self, scope):
scope['user']._wrapped = await get_user(scope)
def TokenAuthMiddlewareStack(inner):
return CookieMiddleware(SessionMiddleware(TokenAuthMiddleware(inner)))
3) 将中间件配置到路由中
3.1)打开routing.py
from channels.routing import ProtocolTypeRouter
from django.urls import path
from channels.routing import ProtocolTypeRouter, URLRouter
from <base-app-name>.middleware import TokenAuthMiddlewareStack
from <app-name>.consumers import <consumer-name>
application = ProtocolTypeRouter({
'websocket': TokenAuthMiddlewareStack(
URLRouter([
path('<route>/', <consumer-name>),
]),
),
})
4)在AsyncWebSocketConsumer的connect方法中检查用户
async def connect(self):
user = self.scope['user']
if user.is_anonymous:
await self.close()
else:
<your logic>