1 简介:
什么是JSON的web令牌?
JWT 是一种验证某些 JSON 数据所有者的机制。它是一个编码的、URL 安全的字符串,可以包含无限量的数据(与 cookie 不同),并且可以经过加密签名。
JWT包含标准字段如aud
(受众)、exp
(过期时间)、iss
(发行者)、sub
(主题)和jti
(唯一标识),用于客户端身份验证。JWT分为自签名类型,如OAuth 2.0中的client_secret_jwt
和private_key_jwt
。
当服务器收到 JWT 时,它可以保证它包含的数据是可信的,因为它是由源签名的。一旦发送加密JWT,任何中间人都无法对其进行修改。
2 JWT常用携带字段
为客户端身份验证(或)创建 JWT 断言声明时,收集 JWT 的有效负载部分的声明信息。声明是有关实体的语句,实体通常是用户和任何其他数据。
可以自定义字段名,也可以使用常用的字段名如下,
字段名 类型描述
aud 尝试使用 JWT 进行身份验证的资源的完整 URL。
例如:https://${yourOktaDomain}/oauth2/default/v1/token 字符串
exp 自 1970 年1月1日的 UTC时间戳(UNIX 时间戳)以来的令牌过期时间(以秒为单位),
例如整数 1557594819
如果过期时间在未来超过一小时或令牌已过期,则此声明会使请求失败。
iss 令牌的颁发者。此值必须与您正在访问的应用程序的值相同。
例如 client_id 字符串 必填。
sub 令牌的主题。此值必须与您正在访问的应用程序的值相同。
例如 client_id 字符串
jti 唯一令牌标识符。如果指定此参数,则令牌只能使用一次,
因此后续令牌请求不会成功。 字符串
iat 例如,UTC(UNIX 时间戳)以来以秒为单位颁发令牌时,
例如整数 1557594819 .如果指定,则必须是收到请求之前的时间。
3 自签名令牌认证 Token Authentication
不同的框架常常有不同的算法实现,比如在OAuth 2.0中常用的可以生成两种类型的自签名 JWT ,以便在向需要客户端身份验证的终结点发出请求时使用:
具有共享密钥 (client_secret_jwt)
带有私钥的 JWT (private_key_jwt)
构建这两种类型的断言之间的区别在于用于对 JWT 进行签名的算法和密钥。
您使用的 JWT 类型取决于客户端应用程序中配置的客户端身份验证方法。
使用共享密钥构建 JWT,如果将应用程序配置为使用客户端身份验证方法,则需要生成使用 HMAC SHA 算法(HS256、HS384 或 HS512)进行签名的 JWT。
令牌认证的主要方法(以及我们将在BlogAPI中实现的一种方法)是使用令牌验证 JSON Web Token (JWT, 发音 jot) 。这是近年来最流行的方法应用程序。
基于令牌的身份验证是无状态的:客户端将初始用户凭据发送至服务器生成唯一的令牌,然后由客户端将其存储为cookie或本地储存。
然后,此令牌在每个传入HTTP请求的标头中传递,服务器使用它来验证用户已通过身份验证。服务器本身不保留用户记录,以及令牌是否有效。
Cookies vs localStorage
Cookies用于读取服务器端信息。它们较小(4KB),并随每个HTTP请求自动发送。 LocalStorage专为客户端信息而设计。它更大(5120KB),默认情况下,不会在每个HTTP请求都发送其内容。
Cookie和localStorage中存储的令牌很容易受到XSS攻击。
目前最佳做法是使用httpOnly和Securecookie标志将令牌存储在cookie中。
让我们看一下此 挑战/响应流 ( challenge/response)中的实际HTTP消息的简单版本。注意HTTP标头WWW-Authenticate指定在响应中使用的令牌的使用授权标头请求。
示意图表 Diagram
Client Server
-------->
GET / HTTP/1.1
<----------- HTTP/1.1 401 Unauthorized WWW-Authenticate: Token
---------->
GET / HTTP/1.1
Authorization:
Token 401f7ac837da4dawdaw613d789819ff93537bee6a
<---------
HTTP/1.1 200 OK
这种方法有很多好处。由于令牌存储在客户端上,因此扩展维护最新会话对象的大型服务器不再是问题。
令牌可以共享在多个前端之间:相同的令牌可以代表网站上的用户,并且相同用户在移动应用上。
Django_REST_Framework 令牌内建库 TokenAuthentication 是很基础的,不支持设置令牌到期,这是可以添加的安全性改进。
它也只会产生一个令牌,因此网站上的用户以及后来的移动应用程序都将使用相同的令牌。
由于有关用户的信息存储在本地,这需要更新两组客户信息 因此可能导致维护和维护方面的问题。
可以添加到Django的令牌的增强版本可以通过多个第三方程序包的REST框架。
JWT有很多好处,包括生成唯一客户端令牌和令牌到期的能力。它们可以在服务器生成或第三方服务(如Auth)。
而且JWT可以被加密,这使得它们可以更安全地通过不安全的HTTP连接发送,也补充了http的不安全性。
4 使用框架自带的功能实现令牌认证
对于大多数Web API而言,最安全的选择是使用基于令牌的身份验证方案。
JWTs是不错的,是现代的补充,尽管它们需要其他配置。
在这里我们将使用rest_framework内置的TokenAuthentication。
第一步 配置我们的新身份验证设置。
Default Authentication
Django REST框架来了具有许多隐式设置的设置。例如,DEFAULT_PERMISSION_CLASSES在我们将其更新为IsAuthenticated之前,将其设置为AllowAny。 明确config/setting默认认证配置如下
REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], 'DEFAULT_AUTHENTICATION_CLASSES': [ # new 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication'], }
要同时使用两种方法,答案是它们有不同的用途。会话用于提供可浏览的API以及登录和注销该API的能力。 BasicAuthentication 用于传递API本身的HTTP标头中的会话ID。
第二步,设置DEFAULT_AUTHENTICATION_CLASSES TokenAuthentication
# config/settings.py REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', # new ],}
第三步,添加token认证到 全局 setting设置 INSTALLED_APPS
'rest_framework.authtoken'
第四步, 我们对INSTALLED_APPS进行了更改,因此我们需要同步数据库
python manager.py migrate
使用superuser 管理员,你会看到那里现在顶部的“令牌”部分。确保您使用超级用户帐户登录后才能有 token 使用权。
由于几乎所有的API需要此功能,因此有几个优秀且经过测试的第三方可以满足 token的创建和管理功能。
5 小结
请注意,JWT 保证数据所有权,但不保证加密。
任何截获令牌的人都可以看到存储到 JWT 中的 JSON数据,因为它只是序列化的,而不是加密的。
出于这个原因,强烈建议将HTTPS与JWT(顺便说一下,还有一般的HTTPS)一起使用。
JWT 是一种特别有用的 API 身份验证和服务器到服务器授权技术。
但是会话操作时, 不应将 JWT 用作会话令牌。
首先,JWT 具有广泛的功能和大范围适用场景,这增加了库作者或用户出错的可能性。
其次是,您无法在会话结束时删除 JWT,因为它是独立的,并且没有中央机构使它们无效。
最后, JWT相对较大。当与 cookie 一起使用时,每个请求都传输可能增加开销。
主要局限性:
相同的会话ID不能在不同的前端之间共享
缺点:
潜在的不利因素是令牌可能会变得很大。令牌包含所有用户信息,不仅是ID,还有会话ID /会话对象的设置。
由于令牌是根据每个请求发送的,管理其大小可能会成为性能问题。
令牌的实施方式也可能有很大不同。
总体而言,这是一种非常流行的标准,可用于通过使用签名来信任请求,并在各方之间交换信息。
JWT 的一个非常常见的用途——也许是最好的用途——是作为 API 身份验证机制。
确保您知道何时最好使用,何时最好使用其他方法,以及如何防止最基本的安全问题。