免费获得官方JWT手册并深入学习JWT吧!

简介

JSON Web Token(缩写JWT),是一套开放的标准(RFC 7519),它定义了一种紧凑且自URL安全的方式,以JSON对象的方式在各方之间安全地进行信息传输。由于此信息是经过数字签名的,因此是可以被验证和信任的。可以使用密钥(secret)(使用HMAC算法)或者使用RSA或ECDSA的公有/私有密钥对JWT进行签名。

虽然可以对JWT进行加密用来在各方之间提供保密性,但我们还是重点关注下签名的令牌(token)本身,签名的令牌可以验证其中包含的声明的完整性,而加密的令牌则将这些声明在其他方的面前进行隐藏,以提供安全性。当使用公钥/私钥对对令牌进行签名时,签名还可以证明只有持有私钥的一方才是对其进行签名的一方。

JWT应用场景

一些常用到JWT的情况:

  • 授权:这是使用JWT的最常见方案。一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。单点登录是当今广泛使用JWT的一项功能,因为它的开销很小并且支持跨域。
  • 信息交换:JWT是在各方之间安全地传输信息的好方法。因为可以对JWT进行签名(例如,使用公钥/私钥对)。此外,由于签名是使用Header和Payload计算的,因此还可以验证内容是否遭到篡改。

JWT数据结构

JSON Web Token以紧凑的形式由三部分组成,这些部分由点(.)分隔,分别是:

  • Header
  • Payload
  • Signature

大致格式如下所示:

xxxxx.yyyyy.zzzzz

下面来看下具体每个部分:

Header

Header通常由两部分组成的一个JSON对象:令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。例如:

{
"alg": "HS256",
"typ": "JWT"
}

最后,将上面的 JSON 对象使用Base64URL编码(转成字符串作为第一部分。

Payload

第二部分是包含声明的Payload(有效载荷),声明是有关实体(通常是用户信息)以及一些额外数据的说明,用来传递实际的数据。声明有三种类型:

  • 标准注册的声明:这些是一组非强制性的但建议使用的预定义字段集,用来提供有用、可互操作的声明。

以下官方提供的一些字段,完整字段可查看标准文档

iss: jwt签发者

sub: jwt所面向的用户

aud: 接收jwt的一方

exp: jwt的过期时间,这个过期时间必须要大于签发时间

nbf: 定义在什么时间之前,该jwt都是不可用的.

iat: jwt的签发时间

jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

注意:以上声明的字段仅是三个字符,因为JWT是紧凑的。

  • 公共的声明:这些声明可以由使用JWT的人进行自定义. 但是为了避免冲突,这些声明应该在IANA JSON Web Token Registry中定义过,或者被定义为包含一个抗冲突名称空间的URI

  • 私有的声明:这些是自定义的声明,用于在双方同意使用它们的情况下共享信息,而不是注册或公开声明。一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

例如,定义一个payload:

{
"sub": "1234567890", // 标准声明
"name": "John Doe", // 公共声明
"admin": true // 自定义
}

然后,同样地对payload进行Base64Url编码,作为JSON Web Token的第二部分。

对于已签名的令牌(token),尽管信息可以防止篡改,但任何人都可以读取。除非将其加密,否则请勿将敏感信息放入JWT的Payload或Header元素中。

Signature

Signature 部分是对前两部分的签名,防止数据篡改。

要生成签名部分,需求根据编码的Header,编码的Payload,一个指定的密钥(secret),通过Header指定的算法(默认是HMAC SHA256算法),然后生成签名。

例如,如果要使用HMAC SHA256算法,则将通过以下方式创建签名:

HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

生成JWT

最后把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。

输出是三个由点分隔的Base64-URL字符串,可以在HTML和HTTP环境中轻松传递这些字符串,与基于XML的标准(例如SAML)相比,它更紧凑。

下面显示了一个JWT,它已对先前的Header和Payload进行了编码,并用一个密钥(secret)进行签名。

如果你想实践下,可以使用jwt.io.debugger在线解码、验证及生成JWT。

Base64URL

前面提到,Header 和 Payload 串型化的算法是 Base64URL。这个算法跟 Base64 算法基本类似,但有一些小的不同。

JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。这就是 Base64URL 算法。

JWT如何使用?

在身份验证中,当用户使用其凭据成功登录后,将返回JSON Web Token。由于令牌(token)是凭据,因此必须格外小心以防止安全问题。通常,令牌的有效时间不应超过要求的时间。

由于缺乏安全性,也不应该将敏感的会话数据存储在浏览器中。

当用户想访问受保护的路由或者资源时,用户代理(比如浏览器)需要带上JWT,一般是在请求头里加入Authorization,并加上Bearer标注:

headers: {
'Authorization': 'Bearer ' + token
}

在某些情况下,这可以是无状态授权机制。服务器的受保护路由将在Authorization标头中检查有效的JWT ,如果存在,则将允许用户访问受保护的资源。如果JWT包含必要的数据,则可以减少查询数据库中某些操作的需求,尽管这种情况并非总是如此。

如果令牌是在Authorization标头中发送的,则不会有跨域资源共享(CORS)的问题,因为不使用cookie。

另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。

下图显示了如何获取JWT并将其用于访问API或资源:

1、应用程序或客户端向授权服务器请求授权。

2、授予授权后,授权服务器会将访问令牌返回给应用程序。

3、该应用程序使用访问令牌来访问受保护的资源(例如API)。

为什么要使用JWT?

SWT和SAML对比

让我们谈谈与简单Web令牌(Simple Web Tokens,SWT)和 安全性声明标记语言令牌(Security Assertion Markup Language Tokens,SAML)相比,JSON Web令牌(JWT)的好处。

由于JSON不如XML冗长,在编码时JSON的大小也较小,从而使JWT比SAML更为紧凑。这使得JWT是在HTML和HTTP环境中传递的不错的选择。

在安全方面,SWT只能使用HMAC算法的共享密钥对其进行对称签名。但是,JWT和SAML令牌可以使用X.509证书形式的公用/专用密钥对进行签名。与签名JSON的简单性相比,使用XML数字签名对XML进行签名而不引入一些的安全漏洞是非常困难的。

JSON解析器在大多数编程语言中都很常见,因为它们直接映射到对象。相反,XML没有自然的文档到对象映射。与SAML断言相比,JWT更加简单易用。

编码的JWT和编码的SAML的长度比较:

传统Session/Cookie的认证对比

基于Cookie的身份认证

身份认证的一般流程:

但是http是无状态协议,这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发出的请求。

传统的解决方案是创建所谓的“会话(Session)”,会话分为两个部分:

1、存储在服务端上的对象,用于记住用户是否仍在登录,对其个人资料的引用等。

2、客户端上的cookie,其中存储了某种ID,可以在服务器上根据会话对象的ID对其进行引用。

身份验证过程如下:

通过从登录页面向服务端发送用户名/密码组合来创建新会话。如果服务器可以使用该用户名和密码来匹配用户,它将在服务器上生成一个新的会话对象,并在客户端上设置一个带有该会话ID的cookie。后续用户发出的请求需要带上cookie,服务端就可以验证是哪个用户以及验证会话是否有效。

基于Cookie认证的缺点

以上模式在单机上没有问题。问题在于扩展性不好,存在以下问题:

  • 多个服务端:当使用多个后端进行身份验证时,事情可能会变得复杂(例如,可以通过中央应用服务器代理所有请求,然后需要了解每个辅助服务的所有逻辑,或者每个服务都可以实现复杂的服务器间通信(和CORS),以使用中央身份验证服务器验证传入的会话ID。在任何一种情况下,都需要在应用服务器上增加额外的负载,并且需要维护更复杂的互连)。
  • 会话:需要存储在内存,数据库或Redis之类的键值存储中的某个位置;并且需要对其进行管理,以使其在到期或无效时被删除。
  • 可伸缩性差:扩展服务器时需要扩展会话存储,增加了复杂性。
  • 性能问题:当会话需要存储在服务器上时,每个数据库请求都需要进行很多数据库/存储查找,这会使服务器陷入瘫痪。
  • CSRF:如果正在使用cookie,则需要额外的安全性来防止跨站点请求攻击,因为cookie会随该站点的任何请求一起自动发送到服务器。
  • CORS:Cookie + CORS在不同的域中表现不佳(实际上,真正的跨域根本不起作用)。

而使用JWT,你可以使用应用程序注册自己(与使用老式应用程序几乎相同),然后使用凭据(例如,用户名/密码或第三方OAuth)登录。但是服务器不会进行会话和设置Cookie,而是向你发送JSON Web令牌。然后,你可以使用该令牌来完成对服务器的任何操作。

后记

以上译文仅用于学习交流,水平有限,难免有错误之处,敬请指正。

链接

JSON Web Token 是什么?的更多相关文章

  1. 使用Json Web Token设计Passport系统

    >>Token Auth机制 基于Token的身份验证是无状态的,我们不将用户信息存在服务器或Session中. 相比原始的Cookie+Session方式,更适合分布式系统的用户认证,绕 ...

  2. JWT【JSON Web Token】 简述

    draft: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html http://tools.ietf.org/html/ ...

  3. 八幅漫画理解使用JSON Web Token设计单点登录系统

    用jwt这种token的验证方式,是不是必须用https协议保证token不被其他人拦截? 是的.因为其实只是Base64编码而已,所以很容易就被解码了.如果你的JWT被嗅探到,那么别人就可以相应地解 ...

  4. JSON Web Token - 在Web应用间安全地传递信息(zhuan)

    来自 http://blog.leapoahead.com/2015/09/06/understanding-jwt/ JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允许我们使用 ...

  5. JSON Web Token

    What is JSON Web Token? JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact a ...

  6. [认证授权] 2.OAuth2(续) & JSON Web Token

    0. RFC6749还有哪些可以完善的? 0.1. 撤销Token 在上篇[认证授权] 1.OAuth2授权中介绍到了OAuth2可以帮我们解决第三方Client访问受保护资源的问题,但是只提供了如何 ...

  7. Hacking JWT(JSON Web Token)

    0x01 JWT工作流程 JSON Web Token(JWT)是一个非常轻巧的规范. 这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息. JWT常被用于前后端分离,可以和Restful ...

  8. 什么是JWT(JSON WEB TOKEN)

    转自于:http://www.jianshu.com/p/576dbf44b2ae 什么是JWT Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准( ...

  9. JSON Web Token - 在Web应用间安全地传递信息

    转载自:http://blog.leapoahead.com/2015/09/06/understanding-jwt/ JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允许我们使 ...

  10. JWT(JSON Web Token) 多网站的单点登录,放弃session

    多个网站之间的登录信息共享, 一种解决方案是基于cookie - session的登录认证方式,这种方式跨域比较复杂. 另一种替代方案是采用基于算法的认证方式, JWT(json web token) ...

随机推荐

  1. freemarker<二>

    一.FreeMarker模板文件组成 ①.文本,直接输出的部分 ②.注释,即<#--...-->格式不会输出 ③.FTL指令:FreeMarker指令,和HTML标记类似,名字前加#予以区 ...

  2. Struts2和Spring集成

    Spring是一个流行的Web框架,它提供易于集成与很多常见的网络任务.所以,问题是,为什么我们需要Spring,当我们有Struts2?Spring是超过一个MVC框架 - 它提供了许多其它好用的东 ...

  3. centos7 断电导致 generating /run/initramfs/rdsosreport.txt 问题

    开机就进入命令窗口,窗口提示信息如下: generating “/run/initramfs/rdsosreport.txt” entering emergencymode. exit the she ...

  4. Visio常规图表

    包含的就是一些形状模块 比如框图就包含了“方块”以及“具有凸起效果的块”两个形状模版 打开visio 新建的时候选择常规类别 具有透视效果的框图 下面是基本操作: 这是自动调整大小的框 不能调整大小 ...

  5. Visio模具与模版

    yy 这些形状就是模具 点击更多形状 然后新建模具 也可以打开已有的模具 模具名字右边有星号 代表模具未保存 鼠标右键单击可以选择保存 选择属性可以进行设置(信息之类的)也可以进行关闭 模具文件三种打 ...

  6. 第二阶段:4.商业需求文档MRD:3.PRD-页面结构图

    这也是功能结构以及优先级 这是页面层级 页面结构图 再细分某一个频道或者子页面 层层细分 用mind做的页面结构图 里面也包含了功能

  7. jquery中如何判断checkbox是否选中

    jquery代码: <script> $(document).ready(function() { $('#checkbox-id').click(function() { if($('# ...

  8. 深度兴趣网络DIN-SIEN-DSIN

    看看阿里如何在淘宝做推荐,实现"一人千物千面"的用户多样化兴趣推荐,首先总结下DIN.DIEN.DSIN: 传统深度学习在推荐就是稀疏到embedding编码,变成稠密向量,喂给N ...

  9. echo 传义序列

    echo 传义序列:\a 警示字符\b 退格\c 输出中忽略最后的换行符\f 清屏\n 换行\r 回车\t 水平制表符\v 垂直制表符\\ 反斜杠字符\0ddd 将字符表示成1到3位的八进制数值

  10. OOP之重载

    PHP中的重载指的是动态的创建属性与方法,是通过魔术方法来实现的. 属性的重载通过调用类中的__set,__get,__isset,__unset方法来分别实现对不存在属性的赋值.读取.判断属性是否设 ...