使用Json Web Token设计Passport系统

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 基于Token的身份验证是无状态的,不将用户信息存在服务器或Session中, 相比原始的Cookie+Session方式,更适合分布式系统的用户认证,绕开了传统的分布式Session一致性等问题,可以采用标准化的 JSON Web Token (JWT),对以后系统接入Node等纯前端开发更便捷

一、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以后就可以得到用户敏感信息;

 

 

参考资料:

基于 Token 的身份验证

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

 

目录
相关文章
|
3月前
|
XML JSON 前端开发
【Web前端揭秘】XML与JSON:数据界的双雄对决,你的选择将如何改写Web世界的未来?
【8月更文挑战第26天】本文深入探讨了XML和JSON这两种广泛使用的数据交换格式在Web前端开发中的应用。XML采用自定义标签描述数据结构,适用于复杂层次数据的表示,而JSON则以键值对形式呈现数据,更为轻量且易解析。通过对两种格式的示例代码、结构特点及应用场景的分析,本文旨在帮助读者更好地理解它们的差异,并根据实际需求选择最合适的数据交换格式。
60 1
|
21天前
|
存储 消息中间件 缓存
构建互联网高性能WEB系统经验总结
构建互联网高性能WEB系统经验总结
|
1月前
|
机器学习/深度学习 数据处理 数据库
基于Django的深度学习视频分类Web系统
基于Django的深度学习视频分类Web系统
53 4
基于Django的深度学习视频分类Web系统
|
19天前
|
负载均衡 监控 算法
论负载均衡技术在Web系统中的应用
【11月更文挑战第4天】在当今高并发的互联网环境中,负载均衡技术已经成为提升Web系统性能不可或缺的一环。通过有效地将请求分发到多个服务器上,负载均衡不仅能够提高系统的响应速度和处理能力,还能增强系统的可扩展性和稳定性。本文将结合我参与的一个实际软件项目,从项目概述、负载均衡算法原理以及实际应用三个方面,深入探讨负载均衡技术在Web系统中的应用。
48 2
|
1月前
|
机器学习/深度学习 监控 数据挖掘
基于Django和百度飞桨模型的情感识别Web系统
基于Django和百度飞桨模型的情感识别Web系统
37 5
|
1月前
|
存储 JSON 前端开发
JSON与现代Web开发:数据交互的最佳选择
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也便于机器解析和生成。它以文本格式存储数据,常用于Web应用中的数据传输,尤其是在客户端和服务器之间。
44 0
|
2月前
|
网络协议 Windows
[收藏]优化基于Win 2000系统的Web服务器性能
[收藏]优化基于Win 2000系统的Web服务器性能
|
3月前
|
API 数据库 开发者
解锁Web2py新境界!揭秘如何利用神秘插件系统,让你的Web项目瞬间起飞?
【8月更文挑战第31天】Web2py是一款轻量级且功能全面的Python Web框架,其插件系统允许开发者在不修改核心代码的情况下扩展框架功能,提升项目灵活性和可扩展性。本文介绍如何利用Web2py插件系统增强Web项目,包括插件的优势、选择与安装方法,并通过集成身份认证插件的具体示例展示其应用过程。通过合理利用插件,可以显著提高开发效率和用户体验。
53 1
|
3月前
|
缓存 NoSQL 数据库
Web服务器与数据库优化:提升系统性能的最佳实践
【8月更文第28天】在现代的Web应用中,Web服务器与后端数据库之间的交互是至关重要的部分。优化这些组件及其相互作用可以显著提高系统的响应速度、吞吐量和可扩展性。本文将探讨几种常见的优化策略,并提供一些具体的代码示例。
166 1
|
3月前
|
前端开发 开发者 容器
【Web布局的革命】探索CSS Grid栅格系统,打造未来网页设计!
【8月更文挑战第25天】在网页设计领域,布局至关重要。传统的布局方法难以满足复杂需求,CSS Grid 栅格系统因此诞生。它是一种二维布局模式,能直接控制行和列,简化复杂网格的设计。通过定义 `display: grid;` 创建网格容器,并利用 `grid-template-columns` 和 `grid-template-rows` 设置行列尺寸,轻松实现响应式布局。此外,CSS Grid 支持高级功能,如网格区域划分和对齐设置,极大提升了布局的灵活性和创意空间。随着浏览器兼容性的增强,CSS Grid 必将成为未来网页设计的关键技术之一。
65 1