使用Json Web Token设计Passport系统
一、Token Auth机制
基于Token的身份验证是无状态的,我们不将用户信息存在服务器或Session中。
相比原始的Cookie+Session方式,更适合分布式系统的用户认证,绕开了传统的分布式Session一致性等问题。
基于Token的身份验证的主流程如下:
用户通过用户名和密码发送请求;
程序验证;
程序返回一个签名的token 给客户端;
客户端储存token,并且每次用于每次发送请求。
二、相比Cookie认证的优势
支持跨域跨站点访问:
Cookie是不允许垮域访问的,可以通过设置顶级域名的方式实现部分跨域,但是跨站点的访问仍然不支持,
如果使用Token机制,就可以通过HTTP头传输用户认证信息,从而更好的实现跨域跨站点。
无状态:
Token机制在服务端不需要存储session信息,Token自身包含了登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息;
去耦:不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可;
更适用于移动应用:
当客户端是原生应用时,Cookie是不被支持的,虽然目前Webview的方式可以解决Cookie问题,
但是显然采用Token认证机制会简单得多;
安全性更强:
因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范;
标准化易扩展:
可以采用标准化的 JSON Web Token (JWT),对以后系统接入Node等纯前端开发更便捷;
相比Session一致性提高性能:
相比服务端保存Session一致性信息,并查询用户登录状态,一般来说Token的验证过程(包含加密和解密),性能开销会更小。
三、JSON Web Token标准的设计
JWT 标准的 Token 有三个部分:
header.payload.signature

三个部分中间用点分隔开,并且都使用 Base64 编码,所以生成的 Token 类似这样:
ewogICJ0eXAiOiAiSldUIiwKICAiYWxnIjogIkhTMjU2Igp9.ewogImlzcyI6ICJjaGJsb2dzLmNvbSIsCiAiZXhwIjogIjE0NzA3MzAxODIiLAogInVpZCI6ICIxMjM0NWFiY2RlIiwKfQ.9q2eq8sa374ao2uq9607r6qu6
(1)Header报头
header 部分主要包括两部分,一个是 Token 的类型,另一个是使用的算法,
比如下面类型就是 JWT,使用的算法是 HS256。
{
"typ": "JWT",
"alg": "HS256"
}
Header内容要用 Base64 的形式编码,所以就变成这样:
ewogICJ0eXAiOiAiSldUIiwKICAiYWxnIjogIkhTMjU2Igp9
(2)Payload载荷部分
Payload 里面是 Token 的具体内容,这部分内容可以自定义,JWT有标准字段,也可以添加其它需要的内容。
标准字段:
iss:Issuer,发行者
sub:Subject,主题
aud:Audience,观众
exp:Expiration time,过期时间
nbf:Not before
iat:Issued at,发行时间
jti:JWT ID
这是一个典型的payload信息,包含了发行者(网站)、过期时间和用户id:
{
"iss": "chblogs.com",
"exp": "1470730182",
"uid": "12345abcde",
}
这部分内容同样要用Base64 编码,生成编码类似如下格式:
ewogImlzcyI6ICJjaGJsb2dzLmNvbSIsCiAiZXhwIjogIjE0NzA3MzAxODIiLAogInVpZCI6ICIxMjM0NWFiY2RlIiwKfQ==
(3)Signature签名部分
签名部分主要和token的安全性有关,Signature的生成依赖前面两部分。
首先将Base64编码后的Header和Payload用.连接在一起,
ewogICJ0eXAiOiAiSldUIiwKICAiYWxnIjogIkhTMjU2Igp9.ewogImlzcyI6ICJjaGJsb2dzLmNvbSIsCiAiZXhwIjogIjE0NzA3MzAxODIiLAogInVpZCI6ICIxMjM0NWFiY2RlIiwKfQ
对这个字符串使用HmacSHA256算法进行加密,这个密钥secret存储在服务端,前端不可见,
String str="ewogICJ0eXAiOiAiSldUIiwKICAiYWxnIjogIkhTMjU2Igp9."
+ "ewogImlzcyI6ICJjaGJsb2dzLmNvbSIsCiAiZXhwIjogIjE0NzA3MzAxODIiLAogInVpZCI6ICIxMjM0NWFiY2RlIiwKfQ";
byte[] inputData = str.getBytes();
String key = Coder.initMacKey();
BigInteger sha = new BigInteger(Coder.encryptHMAC(inputData, key));
System.out.println("HS256加密后——"+sha.toString(32));
下面使用密钥 THISSHA 进行加密:
9q2eq8sa374ao2uq9607r6qu6
然后将Signature和前面两部分拼接起来,得到最后的token:
ewogICJ0eXAiOiAiSldUIiwKICAiYWxnIjogIkhTMjU2Igp9.ewogImlzcyI6ICJjaGJsb2dzLmNvbSIsCiAiZXhwIjogIjE0NzA3MzAxODIiLAogInVpZCI6ICIxMjM0NWFiY2RlIiwKfQ.9q2eq8sa374ao2uq9607r6qu6
四、JWT认证的实现
常规的token保存在sessionStorage或者localStorage中,每次请求时将token加在http请求的Header中,
下面是典型的token认证方式:
1.客户端登录时通过账号和密码到服务端进行认证,认证通过后,服务端通过持有的密钥生成Token,Token中一般包含失效时长和用户唯一标识,如用户ID,服务端返回Token给客户端;
2.客户端保存服务端返回的Token;
3.客户端进行业务请求时在Head的Authorization字段里面放置Token,如: 
Authorization: Bearer Token 
4.服务端对请求的Token进行校验,如果Token不是存放在Cookie中,需要解决用户主动注销,但设置的过期时间并未过期问题。
用户注销时可以把还在失效内的Token储存在Redis等缓存中,验证时查找Token是否存在,如果Token在Redis中存在,则说明用户已注销;如果Token不存在,则校验通过。 
5.服务端可以通过从Token取得的用户唯一标识进行相关权限的校验,并把此用户标识赋予到请求参数中,业务可通过此用户标识进行业务处理; 
还有一种方式是把token保存在Cookie中,这时就不需要在服务端保存token的值,用户注销时直接清除Cookie就可以,
这种方式不需要在服务端储存token的值,认证过程如下:

五、JWT标准的安全性
(1)如何访问CSRF攻击

CSRF (Cross Site Request Forgery),指在一个浏览器中打开了两个标签页,其中一个页面通过窃取另一个页面的 cookie 来发送伪造的请求,因为 cookie 是随着请求自动发送到服务端的。
(2)如何保证token的安全性
客户端不需要持有密钥,由服务端通过密钥生成Token;
在JWT中,不应该在Payload里面加入任何敏感的数据,如用户密码等信息,因为payload并没有做加密,只是一个Base64的编码,
攻击者拿到token以后就可以得到用户敏感信息;
参考资料:
JSON Web Token - 在Web应用间安全地传递信息
使用Json Web Token设计Passport系统的更多相关文章
- 八幅漫画理解使用JSON Web Token设计单点登录系统
		
用jwt这种token的验证方式,是不是必须用https协议保证token不被其他人拦截? 是的.因为其实只是Base64编码而已,所以很容易就被解码了.如果你的JWT被嗅探到,那么别人就可以相应地解 ...
 - 八幅漫画理解使用 JSON Web Token 设计单点登录系统
		
原文出处: John Wu 上次在<JSON Web Token – 在Web应用间安全地传递信息>中我提到了JSON Web Token可以用来设计单点登录系统.我尝试用八幅漫画先让大家 ...
 - [转]八幅漫画理解使用JSON Web Token设计单点登录系统
		
上次在<JSON Web Token - 在Web应用间安全地传递信息>中我提到了JSON Web Token可以用来设计单点登录系统.我尝试用八幅漫画先让大家理解如何设计正常的用户认证系 ...
 - 使用JSON Web Token设计单点登录系统
		
用户认证八步走 所谓用户认证(Authentication),就是让用户登录,并且在接下来的一段时间内让用户访问网站时可以使用其账户,而不需要再次登录的机制. 小知识:可别把用户认证和用户授权(Aut ...
 - 使用JSON Web Token设计单点登录系统--转
		
原文地址:https://leon_lizi.gitbooks.io/json-web-token/content/chapter2.html 用户认证八步走 所谓用户认证(Authenticatio ...
 - android 中使用jwt token(json web token)--java
		
http://blog.csdn.net/mingzhnglei/article/details/51119836 下面贴上自己项目中的一个小小的example import com.nimbusds ...
 - JSON Web Token – 在 Web 应用间安全地传递信息
		
出处:子回 使用 JWT 令牌和 Spring Security 来实现身份验证 八幅漫画理解使用JSON Web Token设计单点登录系统
 - JSON Web Token的使用(转载)
		
定义 JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息. 适用场景 1.用于向Web应用传递一些非敏感信息.例如完成加好友.下 ...
 - JSON Web Token的使用
		
定义 JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息. 适用场景 1.用于向Web应用传递一些非敏感信息.例如完成加好友.下 ...
 
随机推荐
- HDU 4081Qin Shi Huang's National Road System(次小生成树)
			
题目大意: 有n个城市,秦始皇要修用n-1条路把它们连起来,要求从任一点出发,都可以到达其它的任意点.秦始皇希望这所有n-1条路长度之和最短.然后徐福突然有冒出来,说是他有魔法,可以不用人力.财力就变 ...
 - C#之索引器
			
实际中不使用这个东西,只做了解 using System; using System.Collections.Generic; using System.Linq; using System.Text ...
 - OpenStack三种类型的NAT转换
			
SNAT SNAT即源网络地址转换,这个NAT路由修改IP包包头中的源IP地址.SNAT功能通常用于让只具有私有IP地址的主机能够访问外网,比如,多个PC使用路由器共享上网,每个PC都配置了内网IP, ...
 - gprs/gsm 在linux下的应用
			
之前有篇随笔整理了一种在裸机下用状态机+超时的机制来操作gprs/gsm,linux下就不需要了,本身有完善的调度机制,在等待的流程中直接sleep就行了. 下面是飞凌OK6410下的 demo, 其 ...
 - maven阿里云中央仓库
			
配置 修改maven根目录下的conf文件夹中的setting.xml文件,内容如下: <mirrors> <mirror> <id>alimaven</id ...
 - window 使用vagrant搭建开发开发环境
			
# -*- mode: ruby -*-# vi: set ft=ruby : # All Vagrant configuration is done below. The "2" ...
 - MySQL模糊搜索的四种用法
			
1,%:表示任意0个或多个字符.可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示. 比如 SELECT * FROM [user] WHERE u_name LIKE '% ...
 - 用uniq来处理文件重复数据--交集,差集,计数等(转)
			
经常有这样的需求:两个文本文件要求取重复的行或只取不重复的,简单的情况下用sort和uniq来处理是非常方便的: 利用现存两个文件,生成一个新的文件 取出两个文件的并集(重复的行只保留一份) 取出两个 ...
 - Git 账户认证的一些问题
			
Mac被水浇了之后,只好用Window 开发了.但是在往Github上提交代码出现了些问题. 1. 提交时总是出现弹出框提示账号认证 之前Mac没有出现过这问题,所以有些怀疑Windows开发环境不友 ...
 - Mac Pro 编译安装 Redis 的 PHP 客户端 phpredis
			
1.去官网下载 redis 扩展源码包 https://github.com/phpredis/phpredis 2.安装 redis 扩展 /usr/local/src/mac-sdk/source ...