热情的八宝粥 · 李嘉欣不在家 男友许晋亨与前妻开心在家用晚膳· 7 月前 · |
豪情万千的路灯 · 张玉萍代总领事线上会见日本国贸促京都总局会长· 10 月前 · |
朝气蓬勃的春卷 · 神话之城:20座城市里的历史光影,从南美到北 ...· 1 年前 · |
踏实的毛衣 · 水鬼的新娘漫画完整版免费阅读-水鬼的新娘漫画 ...· 1 年前 · |
我的Range2应用程序(以打字本编码)有一个简单的身份验证方案:
abc123...
Authorization
头中发送JWT。
现在我想添加websockets。我想知道如何认证那里的用户。因为我不能控制哪些头被发送到websocket服务器(WS),所以我不能发送JWT。
到目前为止,我的想法(尚未实施):
let sock = new WebSocket('wss://example.com/channel/');
open
事件。一旦套接字打开:
type='auth'
payload='JWT_VALUE'
发送消息
auth
类型。接收到后,服务器读取有效负载,验证
JWT_VALUE
并设置
isAuthenticated
标志。
isAuthenticated
的客户端发送任何其他类型的消息,服务器将断开套接字。
两个问题:连接但从不发送JWT的客户端可以占用服务器资源,如果客户端没有经过身份验证,一个更干净的解决方案将阻止握手。
其他想法:
new WebSocket('wss://example.com/channel/<JWT>/')
如何在websockets上验证客户端?假设用户已经通过HTTP登录,并且角2应用程序有一个JWT令牌。
我确定了以下协议:
1. 客户端登录到站点并接收身份验证令牌(JSON令牌)
GET /auth
user: 'maggie',
pwd: 'secret'
// response
{ token: '4ad42f...' }
2. 身份验证的客户端请求websocket连接票。
GET /ws_ticket
Authorization: Bearer 4ad42f...
// response: single-use ticket (will only pass validation once)
{ ticket: 'd76a55...', expires: 1475406042 }
3. 客户端打开websocket,在查询param中发送票证。
var socket = new WebSocket('wss://example.com/channel/?ticket=d76a55...');
4. Websocket服务器()然后在接受握手之前验证票证。
/**
* Receives the URL used to connect to websocket. Return true to admit user,
* false to reject the connection
function acceptConnection($url){
$params = parse_str(parse_url($url, PHP_URL_QUERY));
return validateTicket($params['ticket']);
/** Returns true if ticket is valid, never-used, and not expired. */
function validateTicket($ticket){/*...*/}
客户端打开websocket,在查询param 中发送UserName和密码。
ws://<username>:<password>@<ip-address><path>
$WebSocket('ws://user:123456@127.0.0.0/util')示例:新
使用 djangorestframework-jwt 生成JWT,并使用以下Django-Channel 2中间件。
令牌可以通过djangorestframework-jwt进行设置,如果
JWT_AUTH_COOKIE
WebSocket
被定义为
,则还会发送给 connections
。
settings.py
JWT_AUTH = {
'JWT_AUTH_COOKIE': 'JWT', # the cookie will also be sent on WebSocket connections
}
routing.py:
from channels.routing import ProtocolTypeRouter, URLRouter
from django.urls import path
from json_token_auth import JsonTokenAuthMiddlewareStack
from yourapp.consumers import SocketCostumer
application = ProtocolTypeRouter({
"websocket": JsonTokenAuthMiddlewareStack(
URLRouter([
path("socket/", SocketCostumer),
})
json_token_auth.py
from http import cookies
from channels.auth import AuthMiddlewareStack
from django.contrib.auth.models import AnonymousUser
from django.db import close_old_connections
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
class JsonWebTokenAuthenticationFromScope(BaseJSONWebTokenAuthentication):
Extracts the JWT from a channel scope (instead of an http request)
def get_jwt_value(self, scope):
cookie = next(x for x in scope['headers'] if x[0].decode('utf-8') == 'cookie')[1].decode('utf-8')
return cookies.SimpleCookie(cookie)['JWT'].value
except:
return None
class JsonTokenAuthMiddleware(BaseJSONWebTokenAuthentication):
Token authorization middleware for Django Channels 2
def __init__(self, inner):
self.inner = inner
def __call__(self, scope):
# Close old database connections to prevent usage of timed out connections
close_old_connections()
user, jwt_value = JsonWebTokenAuthenticationFromScope().authenticate(scope)
scope['user'] = user
except:
scope['user'] = AnonymousUser()