在使用
channels
建立websocket连接的时候,需要验证客户端的token,并保存一些关键信息
使用自定义的中间件进行对token的验证,当然,前端需要把 token放在 headers里
1.创建一个中间件,用来验证token
项目目录下,新建一个 middleware 目录,内部创建一个 my_middleware.py 文件
# middleware/my_middleware.py
# 这是一个无需在settings中注册的中间件
import jwt
class WsTokenVerify:
websocket 使用的 token解析中间件
def __init__(self, app):
# Store the ASGI application we were passed
self.app = app
async def __call__(self, scope, receive, send):
headers = scope['headers']
# headers 里面是一个个的元组类似于[(b'User-Agent',b'XXXX'),(b'token',b'XXXXX'),……]
# 从headers中取出token
for k, v in headers:
if k.decode() == 'token':
token = v.decode()
break
# 解析 token
jwt_dict = jwt.decode(token, key=settings.TOKEN_KEY)
except Exception as e:
# 解析失败,则不做任何处理,直接交给视图函数,视图函数会尝试从scope中取出关键信息,失败则会断开websocket连接
return await self.app(scope, receive, send)
# 将客户端的唯一身份标识(关键信息)加入scope
scope['uid'] = jwt_dict['uid']
scope['nickname'] = jwt_dict['nickname']
scope['group_name'] = jwt_dict['group_name']
return await self.app(scope, receive, send)
2.然后改写: 项目目录/项目同名目录/asgi.py文件
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack # django 自带用户身份认证
from middleware.my_middleware import WsTokenVerify # 自己写的用户身份认证
from gps.urls import websocket_urlpatterns # 自定义的路由
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'qixing_app.settings')
django_application = get_asgi_application()
application = ProtocolTypeRouter({
"http": get_asgi_application(),
# 这里需要更改官网示例,将AuthMiddlewareStack改为我们刚才自定义的中间件
"websocket": WsTokenVerify(URLRouter(websocket_urlpatterns))
3.编写视图函数(建立连接部分)
class Connect(AsyncWebsocketConsumer):
async def connect(self):
self.uid = self.scope['uid']
self.nickname = self.scope['nickname']
self.room_group_name = f"channel_{self.scope['group_name']}"
except Exception as e:
# 关键信息获取失败,则断开连接
print("拒绝连接", e)
await self.close()
else:
# Join room group
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
print('建立连接')
await self.accept()