【问题标题】:How to send JWT correctly without being exposed如何在不暴露的情况下正确发送 JWT
【发布时间】:2019-12-21 10:29:21
【问题描述】:

所以我不确定我的问题是否真的适合 stackoverflow,但我会试一试,看看我对 JWT 的了解是否真的正确,或者我是否完全脱离了循环。

所以我创建的是一个服务器 API,它读取从客户端应用发送的 POST 请求并返回承载令牌,这是访问我创建的其余 API 所必需的。

到目前为止,如果用户名和密码与登录名匹配,我有一个创建 Bearer 令牌的服务器 api。

一个简单的 POST 请求看起来像

{'username': 'hello', 'password': 'world'}

所以我所做的是创建了一个从 JWT.IO 站点编码的 JWT,其密码如下所示:

{'username': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImJhcnJ5In0.-TCwkrPr8dq4WqsckaWNG7G2ddn7e97hH0jkQ-1j5Bo',
 'password': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXNzd29yZCI6ImF1dG9zbmtyIn0.mWvxW4xga_OQMLKxf5zfSP4bSV0KzLPSRpqapU-RbAw'}

但是我的主要问题是我应该如何处理客户端应用程序之间的连接 -> 第一个 /token 请求才能获得不记名令牌?

似乎我确实需要以某种方式“硬编码”客户端应用程序中的用户名和密码才能访问我的 API,但我觉得这不是正确的方法,因为那样你就可以读取网络记录并向服务器发送相同的请求,您将永远获得一个新的 Bearer 令牌,您可以操纵我的服务器 api。

我的问题是我应该怎么做才能不能在客户端应用程序中公开我的用户名和密码并且能够通过我的服务器 api 进行操作?因为我的服务器所做的是它使用秘密解码来自 JWT 的用户名和密码,并且如果用户名和密码与我的服务器 api 用户名和密码匹配,则匹配。但是感觉就像通过已经完成编码的 JWT 令牌公开我的用户名和密码,您仍然可以使用这些值并做任何您想做的事情?

客户端应用示例:

import requests

headers = {
    'accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded',
}

data = {'username': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImJhcnJ5In0.-TCwkrPr8dq4WqsckaWNG7G2ddn7e97hH0jkQ-1j5Bo',
        'password': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXNzd29yZCI6ImF1dG9zbmtyIn0.mWvxW4xga_OQMLKxf5zfSP4bSV0KzLPSRpqapU-RbAw'}


response = requests.post('http://127.0.0.1:8000/token', headers=headers, data=data, verify=False)

【问题讨论】:

  • 我不明白为什么您在将凭据发送到服务器以获取不记名令牌时将用户名和密码放入令牌中。令牌的内容对于您获得令牌的每个人都是可读的,因此它增加了零安全性。您通常应该改用 https 连接。
  • @jps 我同意。因为我不确定我还能如何获得令牌。因为我确实需要发送有效的用户名和密码才能从服务器 api 获取 Bearer 令牌。所以这就是我卡住的地方。我不知道我应该做什么:(

标签: python security jwt


【解决方案1】:

根据您的描述,您的用例中的客户端似乎是代表它自己而不是代表人类用户。

在这种情况下,适用的 OAuth2 授权类型称为“客户端凭据”,其中客户端将“授权”标头中的客户端凭据(通常是客户端 ID 和客户端密码)发送到授权服务器。然后,授权服务器将共享一个访问令牌和/或刷新令牌,这些令牌需要存储在客户端的 cookie 中(通常以 JWT 的形式),并与每个后续请求一起发送到资源服务器。 “Authorization”标头的唯一特别之处在于它告诉整个 HTTP 基础设施不要将值缓存在任何共享缓存中。

现在,问题是,我们如何存储客户端密码。我们应该在客户端中对其进行硬编码吗?当然不是。通常最安全的处理方式是将其存储在密码保险柜中。通常,保险库将机密、密码和证书存储在防篡改硬件安全模块 (HSM) 中。 (但在没有保险库的情况下,将秘密以加密形式存储在单独的文件中也是很常见的)。

剩下的唯一问题是,客户端如何连接到 Vault。 Vault 信任该平台(例如 AWS 或 Kubernetes 或任何其他云平台)。当 VM 或容器在这些平台中启动时,平台会在容器中注入一个令牌。然后应用程序将使用令牌连接可以验证令牌真实性的Vault与平台。

【讨论】:

  • 如果保管库没有暴露给任何外部网络(在 VPC 内关闭),那么滥用保管库的唯一方法是从 VPC 本身向其发送请求。在这种情况下,我可以正确地说使用令牌注入(而不是将其存储在配置文件中)不会增加任何额外的安全性?
猜你喜欢
  • 1970-01-01
  • 2010-09-14
  • 2019-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
相关资源
最近更新 更多