JWT是JSON Web Token的缩写,从字面上来看,我们也可以知道JWT的数据格式为JSON对象,而且它也是一种特殊的Token。简单来说,JWT是一种使用JSON格式传递数据的web Token技术。跟Token一样,JWT可用于用户的登录鉴权,是一种用于身份验证和授权的开放标准,定义了一种紧凑简约、自包含的协议格式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
上一篇wiki提到Token不是也是说避免多次查库吗?需要注意的是现在很多关于Token的介绍更多的偏向JWT,而不是传统的Token。
这里讨论的主要是JWT跟我们传统的Token的区别是什么。其实它们的区别主要体现在接收的信息是否需要进入数据库查询信息。
传统的Token需要查库是因为它们通常采用的是基于带状态的用户认证机制,也就是我们前面所说的有状态的Token。在这种有状态的机制下,每个Token就必须与后端存储(比如数据库或者服务器缓存)进行交互,以此来验证Token的合法性和有效性。而我们现在所讲的JWT也就是我们前面所说的无状态Token啦。
与传统的Token不同,JWT将用户信息加密到Token里面,服务器不保存任何用户信息,服务器通过使用保存密钥验证JWT Token的准确性,只要准确即可通过验证。
因此,JWT的出现改善了传统Token需要查库验证用户信息,而JWT不用查库或者少查库,直接在服务端进行校验。因为用户的信息及加密信息包含在JWT的第二分部Payload(有效荷载)和第三部分的Signature(签名)中,只要在服务端进行校验便可,并且校验也是JWT自己实现的。
这里JWT校验是JWT自己实现是指JWT校验过程中,检查JWT合法性的算法是服务器根据JWT中的规范来完成的。在验证JWT时,需要对比从请求中获取到的JWT前面和服务端根据相同的密钥计算出来的签名是否一致,所以我们通常说JWT校验是JWT自己实现,JWT自己提供签名及签名算法规范。
Base64编码和Base64 URL编码都是将二进制数据转换为可读字符串的编码方式,区别在于Base64 URL编码考虑了URL场景下的特殊性。
Base64编码
是一种将二进制数据转化为可读字符串的编码方式,它使用64个ASCII 字符来表示二进制数据中的每一个字节,并且可以减少数据在网络上的传输量。Base64编码使用"+"、"/"和"="三个字符,因此在URL或HTTP报头等场景下可能会出现问题。
Base64URL编码
是正常Base64编码的变种,为了适应URL和HTTP报头等场景,其使用"-"和"_"替代"+"和"/",并且去掉了等于号"=",不足4个字符时,补上需要加密的字符数模4的余数个"="号。这使得Base64 URL编码更加适合于在URL中传输二进制数据,而不会对URL的解析造成问题。
头部(Header) : JWT头部是一个描述JWT元数据的JSON对象,一般在头部会说明签名的方法和令牌的类型。作用:记录令牌类型、签名算法等例如:{"alg":"HS256","type":"JWT"}
有效载荷(Payload):七默认字段+自定义私有字段
作用:携带一些用户信息,例如"userld":"1","username":"mayikt"们,存放信息(可以被解密,不安全),需要注意的是,Payload的内容只经过了Base64编码,对客户端来说当于明文存储,所以不要放置敏感信息。
七默认字段
iss : jwt签发者
sub : jwt所面向的用户
aud : 接收jwt的一方
exp : jwt的过期时间,这个过期时间必须要大于签发时间
nbf : 定义在什么时间之前,该wt都是不可用的.
oiat : jwt的签发时间
jti : jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
Signature=HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)
作用:防止Token被篡改、确保安全性。例如:计算出来的签名,一个字符串。
Header和Payload加上密钥加密而成,用于比对信息,防止篡改Header和Payload。Signature需要使用编码后的header和payload,以及我们提供的一个密钥,然后使用header中的签名算法进行签名,签名的作用是保证JWT没有被篡改过。
Signaturel中常用的签名算法:常见的算法加密方式有SHA,HMAC,RSA和ECDSA等。其中:SHA:是一种散列算法(哈希函数),可以细分为:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。
HMAC: 是对称加密【哈希消息验证码】,加密和解密用的是相同的密钥,主要用于消息防篡改,例如:HMAC SHA256、HMAC SHA384和HMAC SHA512。
RSA: 是基于公私钥非对称)加密的算法,在JWT中主要用作数字签名,算法运行较慢。RSA没有加入随机数,因此如果攻击者遍历猜测所有的原文,可以通过对比相同的加密密文选择出真实原文,为了防止这种情况,RSA加入了padding机制,对数据进行填充。
ECDSA: 是基于椭圆曲线密码学的非对称加密算法,在JWT中同样用作数字签名,有ECDSA with P-256、ECDSA with P-384和ECDSA with P-521等。
1、用户登录,发送数据:首先,用户登录,通过表单提交等方式向服务端发送用户名和密码。这个数据发送请求一般时POST格式。为了进步提高安全性可采用HTTPS协议进行传输,一般时通过SSL加密的HTTPS进行传输,从而避免敏感信息被嗅探。
2、服务端验证信息,返回生成的JWT:服务端核对用户名和密码成功后,将包含用户信息的数据作为JWT的Payload,将其与JWT的Header分别进行Base64编码拼接后签名,形成一个JWT Token,并将其返回给客户端。
3、客户端收到返回的JWT并保存:客户端收到JWT后,将其保存在客户端本地的存储(比如localStorage或SessionStorage)中。
4、客户端后继请求携带JWT:客户端在后继的每次请求时,都要在HTTP请求头中的Authorization属性中携带JWT(可以解决XSS和XSRF问题)。
5、服务端验证JWT有效性:服务端检查客户端传过来的JWT Token,验证其有效性,比如检查签名是否正确、是否过期、Token的接收方是否是自己等等。
6、服务端解码JWT:验证通过后,服务端解析出JWT Token中包含的用户信息,进行其他逻辑操作(一般是根据用户信息得到权限等),返回结果。
总结:JWT具有安全、可扩展、移动、简单和无状态等特点,因此它在分布式环境中广泛使用,例如基于RESTful API架构。
优点展开:
轻量级,解析方便:JWT基于JSON实现,是一个轻量级的身份验证和授权方案,因为它以JSON格式对数据进行传输,并且不需要在服务端进行存储。,而且非常方便解析。
易扩展,可扩展性好:因为JWT是面向JSON的,所以它非常灵活,并且易于与现有应用程序整合。除了包含标识信息外,JWT还可以包含其他元数据,可以在令牌中自定义丰富的内容。
安全性高:JWT可通过非对称加密算法及数字签名技术来隐藏真实数据。通过使用签名来保护数据完整性,确保只有授权用户才能访问受保护的资源。
无状态,对服务端压力小:由于JWT将用户信息加密到Token里面,服务器不保存任何用户信息,不需要在服务器端存储会话状态信息,从而实现了无状态的请求处理,可以减轻服务器负担,占用带宽比较小。同时,由于JWT自身包含用户信息且无法篡改,在服务(网关)中可以自行解析校验出用户信息,对认证服务器(account-svc)压力小。
跨域支持,可移植性好:由于JWT使用的是标准的HTTP协议,因此支持跨域请求和移动端请求。由于JWT是基于网络的,因此它可以在不同的平台和系统之间轻松流通,并使分布式环境中的身份验证过程变得更加容易和安全。
跨语言适用:JWT已经得到了广泛的应用和支持,可以在不同的编程语言、框架和平台之间交换数据。
总结:JWT存在信息过载、安全性依赖密钥、无法禁用和撤回,无状态及后端无法直接统计使用情况等缺点。虽然JWT在许多情况下都很方便,但作为安全机制的缺陷还是存在一些风险。所以JWT一般为了进一步提高安全性页会采用一些措施,比如传输时采用HTTPS等。
缺点展开:
无法修改,可被使用:JWT生成之后无法修改而且JWT是无状态的,如果别人获取到了,别人也能用。
信息过载:JWT中的所有信息都被编码为字符串并存储在一个JSON对象中,一旦存储的信息量过大,那么JWT的长度也会随之增加。令牌长度与其包含用户信息多少正相关,这可能会导致网络传输和存储的开销不断增加,降低系统性能。
安全性依赖密钥:JWT通过密钥进行数字签名或加密来保证安全性,因此任何人掌握了密钥就能够伪造正确的JWT,进而篡改和冒充其他用户的身份。因此,在分发、管理和保护密钥方面需要非常谨慎和严格。
无法禁用和撤回:由于JWT只能由密钥验证其有效性,并将所需的用户信息存储在其中,因此如果想要禁用或撤回某一个JWT,只能够等到它失效或过期才能够完成。这意味着在遇到令牌被盗用或泄露的情况下,用户会处于高度风险状态。
后端无法直接统计:JWT是一种无状态的身份验证机制,因此后端通常无法直接统计JWT的使用情况。然而,虽然后端无法直接统计JWT的使用情况,但是可以采取一些间接的方法来监控JWT的使用情况。例如:前端埋点、记录日志、使用第三方工具等。
Cookie:保存在浏览器中,有大小限制,有状态
Session:保存在服务器中,服务器有资源开销,分布式、跨系统不好实现
Token:客户端可以将token保存到任何地方,无限制,无状态,利于分布式部署
形式不同:Cookie是小型文本文件,Session,是用户状态列表,Token/.JWT是字符串。
存储位置不同:Cookie、Token/JWT存储在客户端;而Session存储在服务端。
存储核心内容不同:Cookie通常表示用户标识信息、会话状态或其余业务相关信息;Session存储敏感数据(比如用户的密码等);而Token/JWT表示会话安全令牌。
安全性不同:Cookie可能面临CSRF/XSS等风险;Session更加地安全,不过由于Session ID可以猜测到,容易被伪造导致Session端口扫描等攻击;Token/JWT则采用了数字签名或其他方式保证了数据的完整性和安全性,应用相对更加安全。
可跨域性不同:通过设置domain和path属性,Cookie能够使用户在不同域名和路径间共享信息;Session只能实现子域名间的数据共享,而Token/JWT不需要考虑域名、路径问题。
占用空间不同:
(1)Cookie只适合小型的数据(单个Cookie通常最多支持4KB的数据存储),无法存储大量数据。
(2)Session可以存储更多,但给服务器造成压力。Session没有严格的限制,可以存储的数据量相对较大,但是与服务器内存大小有关。虽然Session的体积大小并没有明确的限制,但是在实际应用中一般也不会超过几KB。
(3)Token/JWT是一种轻便目高效的方案,Token的大小不同取决于使用的加密算法和使用的Token格式。相对于Cookie和Session,Token一般比较轻量级,通常只需要几十个字节。
Cookie通常适用于轻量级数据;Session更适合小型、散乱位置的内容;而Token/JWT适用于处理分布式系统等较复杂的情形
支持数据类型不同:
Cookie可以存储任何字符串类型的值(例如文本、数字、日期等),但是大小受到限制,一般不超过4KB。和Cookie类似,Session也可以存储各种字符串类型的值,包括文本、数字、日期等。但是,与Cookie不同的是,Session还可以存储复杂的对象类型(例如数组、哈希表、类实例等),这些类型的数据独立于应用程序之外,并在每个会话生命周期内保存。Token可以存储任何类型的数据,也可以存储复杂的JSON对象或者序列化后的二进制数据等类型。但是,建议只存储必要的信息,并避免存储敏感数据,从而保证安全性。
有效期不同,默认生命周期不同:
(1) Cookie默认生命周期为会话级别,也就是说,当用户关闭浏览器或在一定时间段内没有活动时,Cookie将自动失效。如果需要设置Cookie的有效期,则需要在服务器端设置相应参数,比如Expires,当Expires时间到达时,服务器会将该Cookie删除或重新设置。一般来说,Cookie的有效期比较短。如果未设置过期时间,那么Cookie在关闭浏览器时就会被删除。
(2) Session ID的过期时间由Web服务器配置来决定,通常默认为30分钟,也有20分钟到24小时不等的。在服务端,Session的生命周期决定于服务器的配置和超时规则。如果服务器未设置Session过期时间,那么Session将一直存在,直到服务器被关闭或者手动结束。默认情况下,Token使用期限是永久的,只有服务器才能终止该Token。但Token的有效期可由开发者自行设置。JWT则需要在Token中包含过期时间,并且服务器会对Token的有效性进行检查,如果过期,则需要重新获取Token。如果Token未设置有效期,它将永远有效,这可能导致安全问题。
主要应用场景不同:见下面第六点
总结:Cookie通常用于用户的浏览器行为跟踪和个性化设置等方面,Session更多地是进行一些会话管理与服务,Token和JWT则更多的是用于身份认证,在跨域下进行身份认证和授权。其中,JWT更加适合在单页应用程序或分布式系统。
通过在客户端存储数据(如用户ID和一些设置),允许服务器跟踪认证状态。Cookie适合在需要持续跟踪会话状态时使用,例如购物车或社交媒体网站,还可以根据对浏览器行为跟踪分析用户行为,进行个性化的设置及推荐。
之前总结果的常用场景:(1)登录状态及用户信息的管理;(2)跟踪用户行为,统计分析,广告定位;(3)记住用户偏好设置,定制页面;(4)创建购物车;(5)缓存数据,用于搜索历史和浏览记录;(6)跨页面数据传递,实现数据共享与同步
会话适合在需要高度安全性和可靠性的应用程序中使用,例如在线银行或金融服务。对于简单而且不敏感的数据通常使用Cookie保存,如购物车信息、用户在站点的行为记录等;而对于复杂且敏感的数据使用Session保存,如用户的账号信息等。
之前总结果的常用场景:(1)登录状态及用户信息的管理;(2)跟踪用户行为,统计分析,个性化推荐;(3)实现数据共享,多步骤操作;(4)网站安全;(5)处理后台任务;(6)消息提醒及表单数据存储等
包含有关特定用户身份验证的信息,可以防止CSRF攻击。通常,Token是JSON对象,可以在Web应用程序之间进行传输,并在本地存储。Token适合在需要反复跨越多个域进行身份验证和授权时使用,例如REST AP或移动应用程序。
之前总结果的常用场景:(1)身份认证和授权控制 (2)可以作为支付方式,进行数字货币和加密货币交易 (3)可以作为奖励和积分 (4)安全性口令 (5)门禁控制 (6)辅助追溯,进行审查和监视
与Token类似,但它是一种开放的标准(由IETF组织制定),使用JSON对象包含有关用户身份验证的信息,并被数字签名以确保其完整性。JWT适合在需要可扩展性和安全性的Web应用程序中使用,例如单点登录、单页应用程序、前后端分离项目或分布式系统。
之前总结过的常用场景:(1)登录鉴权:(2)信息交换