深入浅出JWT(JSON Web Token )
1. JWT 介绍
JSON Web Token(JWT)是一个开放式标准(RFC 7519),它定义了一种紧凑(Compact)且自包含(Self-contained)的方式,用于在各方之间以JSON对象安全传输信息。 这些信息可以通过数字签名进行验证和信任。 可以使用秘密(使用HMAC算法)或使用RSA的公钥/私钥对对JWT进行签名。
虽然JWT可以加密以提供各方之间的保密性,但我们将重点关注已签名的令牌。 签名的令牌可以验证其中包含的索赔的完整性,而加密令牌隐藏来自其他方的索赔。 当令牌使用公钥/私钥对进行签名时,签名还证明只有持有私钥的方是签名方。
我们来进一步解释一些概念:
- Compact(紧凑):
由于它们尺寸较小,JWT可以通过URL,POST参数或HTTP标头内发送。 另外,尺寸越小意味着传输速度越快。 - Self-contained(自包含):
有效载荷(Playload)包含有关用户的所有必需信息,避免了多次查询数据库。
2. JWT适用场景
- Authentication(鉴权):
这是使用JWT最常见的情况。 一旦用户登录,每个后续请求都将包含JWT,允许用户访问该令牌允许的路由,服务和资源。 单点登录是当今广泛使用JWT的一项功能,因为它的开销很小,并且能够轻松地跨不同域使用。 - Information Exchange(信息交换):
JSON Web Tokens是在各方之间安全传输信息的好方式。 因为JWT可以签名:例如使用公钥/私钥对,所以可以确定发件人是他们自称的人。 此外,由于使用标头和有效载荷计算签名,因此您还可以验证内容是否未被篡改。
3. JWT结构
在紧凑的形式中,JWT包含三个由点(.)分隔的部分,它们分别是:
- Header
- Payload
- Signature
JWT结构通常如下所示:
xxxxx.yyyyy.zzzzz
下面我们分别来介绍这三个部分:
Header
Header通常由两部分组成:令牌的类型,即JWT。和常用的散列算法,如HMAC SHA256或RSA。
例如:
{
"alg": "HS256",
"typ": "JWT"
}
Header部分的JSON被Base64Url编码,形成JWT的第一部分。
Payload
这里放声明内容,可以说就是存放沟通讯息的地方,在定义上有3种声明(Claims):
Registered claims(注册声明):
这些是一组预先定义的声明,它们不是强制性的,但推荐使用,以提供一组有用的,可互操作的声明。 其中一些是:iss
(发行者),exp
(到期时间),sub
(主题),aud
(受众)等。#Registered Claim Names#Public claims(公开声明):
这些可以由使用JWT的人员随意定义。 但为避免冲突,应在IANA JSON Web令牌注册表中定义它们,或将其定义为包含防冲突命名空间的URI。Private claims(私有声明):
这些是为了同意使用它们但是既没有登记,也没有公开声明的各方之间共享信息,而创建的定制声明。
Playload示例如下:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Playload部分的JSON被Base64Url编码,形成JWT的第二部分。
Notice:
请注意,对于已签名的令牌,此信息尽管受到篡改保护,但任何人都可以阅读。 除非加密,否则不要将秘密信息放在JWT的有效内容或标题元素中。这也是很多文章争论jwt安全性原因,不要用 JWT 取代 Server-side 的 Session状态机制。详情请阅读这篇文章:Stop Using Jwt For Sessions.
Signature
第三部分signature用来验证发送请求者身份,由前两部分加密形成。
要创建签名部分,您必须采用编码标头,编码有效载荷,秘钥,标头中指定的算法并签名。
例如,如果你想使用HMAC SHA256算法,签名将按照以下方式创建:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
3. JWT实践
JWT输出的是三个由点分隔的Base64-URL字符串,可以在HTML和HTTP环境中轻松传递,而与基于XML的标准(如SAML)相比,它更加紧凑。
以下JWT示例,它具有先前的标头和有效负载编码,并且使用秘钥进行签名。
我们可以使用jwt.io调试器来解码,验证和生成JWT:
4.JWT工作原理
在身份验证中,当用户使用他们的凭证成功登录时,JSON Web Token将被返回并且必须保存在本地(通常在本地存储中,但也可以使用Cookie),而不是在传统方法中创建会话 服务器并返回一个cookie。
关于存储令牌(Token)的方式,必须考虑安全因素。
参考: #Where to Store Tokens#
无论何时用户想要访问受保护的路由或资源,用户代理都应使用承载方案发送JWT,通常在请求头中的Authorization
字段,使用Bearer
schema:
Authorization: Bearer <token>
这是一种无状态身份验证机制,因为用户状态永远不会保存在服务器内存中。 服务器受保护的路由将在授权头中检查有效的JWT,如果存在,则允许用户访问受保护的资源。 由于JWT是独立的,所有必要的信息都在那里,减少了多次查询数据库的需求。
这使得我们可以完全依赖无状态的数据API,甚至向下游服务提出请求。 无论哪些域正在为API提供服务并不重要,因此不会出现跨域资源共享(CORS)的问题,因为它不使用Cookie。
Notice:
请注意,使用已签名的令牌,令牌中包含的所有信息都会暴露给用户或其他方,即使他们无法更改它。 在JWT中,不应该在Playload里面加入任何敏感的数据,比如像密码这样的内容。如果将用户的密码放在了JWT中,那么怀有恶意的第三方通过Base64解码就能很快地知道你的密码了。
5. 常见问题
① JWT 安全嗎?
Base64编码方式是可逆的,也就是透过编码后发放的Token内容是可以被解析的。一般而言,我们都不建议在有效载荷内放敏感讯息,比如使用者的密码。
② JWT Payload 內容可以被伪造嗎?
JWT其中的一个组成内容为Signature,可以防止通过Base64可逆方法回推有效载荷内容并将其修改。因为Signature是经由Header跟Payload一起Base64组成的。
③ 如果我的 Cookie 被窃取了,那不就表示第三方可以做 CSRF 攻击?
是的,Cookie丢失,就表示身份就可以被伪造。故官方建议的使用方式是存放在LocalStorage中,并放在请求头中发送。
④ 空间及长度问题?
JWT Token通常长度不会太小,特别是Stateless JWT Token,把所有的数据都编在Token里,很快的就会超过Cookie的大小(4K)或者是URL长度限制。
⑤ Token失效问题?
- 无状态JWT令牌(Stateless JWT Token)发放出去之后,不能通过服务器端让令牌失效,必须等到过期时间过才会失去效用。
- 假设在这之间Token被拦截,或者有权限管理身份的差异造成授权Scope修改,都不能阻止发出去的Token失效并要求使用者重新请求新的Token。
6. JWT使用建议
- 不要存放敏感信息在Token里。
- Payload中的
exp
时效不要设定太长。 - 开启
Only Http
预防XSS攻击。 - 如果担心重播攻击(replay attacks )可以增加
jti
(JWT ID),exp
(有效时间) Claim。 - 在你的应用程序应用层中增加黑名单机制,必要的时候可以进行Block做阻挡(这是针对掉令牌被第三方使用窃取的手动防御)。
[1] Stop using JWT for sessions:
http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
[3] Use JWT The Right Way!:
https://stormpath.com/blog/jwt-the-right-way
[2] JSON Web Token 维基百科:
https://en.wikipedia.org/wiki/JSON_Web_Token
深入浅出JWT(JSON Web Token )的更多相关文章
- Java JWT: JSON Web Token
Java JWT: JSON Web Token for Java and Android JJWT aims to be the easiest to use and understand libr ...
- 如何在SpringBoot中集成JWT(JSON Web Token)鉴权
这篇博客主要是简单介绍了一下什么是JWT,以及如何在Spring Boot项目中使用JWT(JSON Web Token). 1.关于JWT 1.1 什么是JWT 老生常谈的开头,我们要用这样一种工具 ...
- JWT(JSON Web Token) 【转载】
JWT(JSON Web Token) 什么叫JWTJSON Web Token(JWT)是目前最流行的跨域身份验证解决方案. 一般来说,互联网用户认证是这样子的. 1.用户向服务器发送用户名和密码. ...
- [更新]一份包含: 采用RSA JWT(Json Web Token, RSA加密)的OAUTH2.0,HTTP BASIC,本地数据库验证,Windows域验证,单点登录的Spring Security配置文件
没有任何注释,表怪我(¬_¬) 更新: 2016.05.29: 将AuthorizationServer和ResourceServer分开配置 2016.05.29: Token获取采用Http Ba ...
- ( 转 ) 什么是 JWT -- JSON WEB TOKEN
什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...
- 关于JWT(Json Web Token)的思考及使用心得
什么是JWT? JWT(Json Web Token)是一个开放的数据交换验证标准rfc7519(php 后端实现JWT认证方法一般用来做轻量级的API鉴权.由于许多API接口设计是遵循无状态的(比如 ...
- 什么是JWT(Json Web Token)
什么是 JWT (Json Web Token) 用户认证是计算机安全领域一个永恒的热点话题. JWT 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519). 该to ...
- API安全验证之JWT(JSON WEB TOKEN) OLCMS
假如www.olcms.com/getUserInfo获取用户信息,你怎么知道当前用户是谁?有人说登陆时候我把他UID写入session了,如果是API接口,没有session怎么办,那么就需要把UI ...
- 5分钟搞懂:JWT(Json Web Token)
https://www.qikegu.com/easy-understanding/892 JWT 基于token的用户认证原理:让用户输入账号和密码,认证通过后获得一个token(令牌),在toke ...
随机推荐
- Hibernate之多对多表,操作实例
多表操作之多对多关系简介 思路就是: 在数据库底层通过添加中间表来指定关联关系. 在双方的实体中添加一个保存对方的集合 在双方的配置文件中使用set标签和many-to-many标签来进行关联关系的配 ...
- Android读取网络图片到本地的简约的实现
今天在网上看到了一个关于读取网络文件的小视频,觉得不错,拿来与大家分享 思路 具体的思路比较的简单,但是思想非常的单纯.那就是输入一个网址,点击按钮,将从网络上获取的一张图片显示到一个ImageVie ...
- 【图的DFS】图的DFS非递归算法
在DFS的递归算法中,DFS框架如下: 1访问起点v0 2依次以v0的未访问的连接点为起点,DFS搜索图,直至图中所有与v0路径相通的顶点都被访问. 3若该图为非连通图,则图中一定还存在未被访问的顶点 ...
- UNIX网络编程——内网与外网间通信
QQ是一个基于TCP/UDP协议的通讯软件 发送消息的时候是UDP打洞,登陆的时候使用HTTP~因为登陆服务器其实就是一个HTTP服务器,只不过不是常用的那些,那个服务器是腾讯自行开发的!!! 一.登 ...
- Intent的Component,Action和Category属性详解-android学习之旅(五十)
Component属性 代码示例 public class MainActivity extends Activity{ @Override protected void onCreate(Bundl ...
- mysql进阶(二十四)防御SQL注入的方法总结
防御SQL注入的方法总结 这篇文章主要讲解了防御SQL注入的方法,介绍了什么是注入,注入的原因是什么,以及如何防御,需要的朋友可以参考下. SQL注入是一类危害极大的攻击形式.虽然危害很大,但是防御却 ...
- 《java入门第一季》之Socket编程通信和TCP协议通信图解
Socket编程通信图解原理: TCP协议通信图解
- Web Service进阶(六)SOAPBinding绑定方式异常 is not found. Have you run APT to generate them
当在类中填充相应方法时,提示如下错误: 出现以上错误的原因就是在注解中没有添加@SOAPBinding(style=SOAPBinding.Style.RPC)这句话.估计也与JDK的版本相关,这方面 ...
- Java中常用的正则表达式
常用的正则表达式 匹配中文字符的正则表达式: [\u4e00-\u9fa5] 匹配双字节字符(包括汉字在内):[^\x00-\xff] 匹配空行的正则表达式:\n[\s| ]*\r 匹配HTML标记的 ...
- C++ Primer 有感(标准库set类型)
set容器只是单纯的键的集合,键必须为一.set容器不支持下标操作,而且没有定义maped_type类型.在set容器中,value_type不是pair类型,而是与key_type类型相同的类型. ...