首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Websocket、R角2和JSON Web令牌身份验证

Websocket、R角2和JSON Web令牌身份验证
EN

Stack Overflow用户
提问于 2016-09-25 21:33:59
回答 3查看 21.5K关注 0票数 26

我的Range2应用程序(以打字本编码)有一个简单的身份验证方案:

  • 用户登录:
  • 服务器返回JSON令牌(JWT) abc123...
  • 在每个API调用中,应用程序在Authorization头中发送JWT。
  • 服务器验证JWT并授予访问权限。

现在我想添加websockets。我想知道如何认证那里的用户。因为我不能控制哪些头被发送到websocket服务器(WS),所以我不能发送JWT。

到目前为止,我的想法(尚未实施):

  • 客户端打开websocket:let sock = new WebSocket('wss://example.com/channel/');
  • WS服务器接受握手,无需任何身份验证检查。标准HTTP报头在此阶段可用。
  • 客户端侦听套接字上的open事件。一旦套接字打开:
    • 客户端用type='auth' payload='JWT_VALUE'发送消息

  • WS服务器期望套接字上的第一条消息为auth类型。接收到后,服务器读取有效负载,验证JWT_VALUE并设置isAuthenticated标志。
    • 如果验证失败,服务器将断开套接字。
    • 如果没有isAuthenticated的客户端发送任何其他类型的消息,服务器将断开套接字。

两个问题:连接但从不发送JWT的客户端可以占用服务器资源,如果客户端没有经过身份验证,一个更干净的解决方案将阻止握手。

其他想法:

  • 客户端可以在路径中发送JWT:new WebSocket('wss://example.com/channel/<JWT>/')
    • pro:在握手过程中可以获得这些信息。
    • con:路径似乎不是JWT的“合适”位置。具体而言,因为中间代理和访问日志将保存路径;在设计HTTP时,我已经决定不将JWT包含在url中。

  • 服务器可以读取客户端的IP + UserAgent,并与发出JWT时由HTTP服务器创建的DB记录相匹配。然后服务器将猜测是谁在连接。
    • pro:这个信息可以在握手时获得(不确定IP)。
    • con:“猜测”客户端应该与JWT关联,而客户机一开始就没有给出过JWT,这似乎是非常不安全的。例如,这意味着有人欺骗受害者的UA并使用相同的网络(代理、公共wifi、大学内联网.)就能模仿受害者了。

如何在websockets上验证客户端?假设用户已经通过HTTP登录,并且角2应用程序有一个JWT令牌。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-10-02 10:41:07

我确定了以下协议:

1.客户端登录到站点并接收身份验证令牌(JSON令牌)

代码语言:javascript
运行
复制
GET /auth
{
    user: 'maggie',
    pwd:  'secret'
}

// response
{ token: '4ad42f...' }

2.身份验证的客户端请求websocket连接票。

代码语言:javascript
运行
复制
GET /ws_ticket
Authorization: Bearer 4ad42f...

// response: single-use ticket (will only pass validation once)
{ ticket: 'd76a55...', expires: 1475406042 }

3.客户端打开websocket,在查询param中发送票证。

代码语言:javascript
运行
复制
var socket = new WebSocket('wss://example.com/channel/?ticket=d76a55...');

4. Websocket服务器()然后在接受握手之前验证票证。

代码语言:javascript
运行
复制
/**
* 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){/*...*/}
票数 26
EN

Stack Overflow用户

发布于 2019-06-02 21:46:12

使用djangorestframework-jwt生成JWT,并使用以下Django-Channel 2中间件。

令牌可以通过djangorestframework-jwt进行设置,如果JWT_AUTH_COOKIE WebSocket 被定义为,则还会发送给 connections

settings.py

代码语言:javascript
运行
复制
JWT_AUTH = {
    'JWT_AUTH_COOKIE': 'JWT',     # the cookie will also be sent on WebSocket connections
}

routing.py:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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):
        try:
            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):

        try:
            # 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()

        return self.inner(scope)


def JsonTokenAuthMiddlewareStack(inner):
    return JsonTokenAuthMiddleware(AuthMiddlewareStack(inner))
票数 2
EN

Stack Overflow用户

发布于 2017-07-05 05:59:27

客户端打开websocket,在查询param中发送UserName和密码。

代码语言:javascript
运行
复制
ws://<username>:<password>@<ip-address><path>

$WebSocket('ws://user:123456@127.0.0.0/util')示例:新

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39692065

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档