一、简介
1、什么是JWT
JWT(JSON Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑且独立的方式,可以在各方之间作为JSON对象安全地传输信息。此信息可以通过数字签名进行验证和信任。JWT可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
也就是通过JSON形式作为 Web应用中的令牌,用于在各方之间安全的将信息作为JSON对象传输。在数据传输过程中还可以完成数据加密、签名等相关处理。
2、什么时候应该用JWT
下列场景中使用JSON Web Token是很有用的:
-
Authorization (授权) : 这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。
-
Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWT可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。
3、为什么使用JWT?
我们先看一下传统的认证方式
HTTP协议是无状态的,也就是说,如果我们已经认证了一个用户,那么他下一次请求的时候,服务器不知道我是谁,我们必须再次认证
传统的做法是将已经认证过的用户信息存储在服务器上,比如Session。用户下次请求的时候带着Session ID,然后服务器以此检查用户是否认证过。
session 认证:
用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session 请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器 浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名 当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。
根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。
session认证暴露的问题
1、每次用户认证通过以后,服务器需要创建一条记录保存用户信息,通常是在内存中,随着认证通过的用户越来越多,服务器的在这里的开销就会越来越大。 2、用户认证之后,服务端做认证记录,如果认证的记录保存在内存中,这意味着用户下次请求还需请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应限制了负载均衡的能力。这也意味着限制了应用的扩展能力。 3、因为是基于cookie来进行用户识别的,cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击
cookie+session这种模式通常是保存在内存中,而且服务从单服务到多服务会面临的session共享问题,随着用户量的增多,开销就会越大。而JWT只需要服务端生成token,客户端保存这个token,每次请求携带这个token,服务端认证解析即可。
4、JWT认证流程和特点
认证流程:
前端将用户的登录信息发送给服务器; 服务器接受请求后为用户生成独一无二的认证信息--token,传给客户端浏览器; 客户端将token保存在cookie或者storage中; 在之后访问客户端都携带这个token请求服务器; 服务器验证token的值,如果验证成功则给客户端返回数据。
特点:
1)三部分组成,每一部分都进行字符串的转化 2)解密的时候没有使用数据库,仅仅使用的是secret进行解密 3)JWT的secret千万不能泄密!
5、JWT的组成
JWT的组成分为三部分,它们之间用圆点(.)连接
Header 头部 Payload 载荷 Signature 签名
Header(头部)
header部分,即头信息,包含两部分,alg:算法名称、typ:token的类型
{
'alg':"HS256",
'typ':"JWT"
}
将头部使用base64编码加密,构成第一部分
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload(载荷)
载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分
标准中注册的声明 (建议但不强制使用) :
iss: jwt签发者 sub: jwt所面向的用户 aud: 接收jwt的一方 exp: jwt的过期时间,这个过期时间必须要大于签发时间 nbf: 定义在什么时间之前,该jwt都是不可用的. iat: jwt的签发时间 jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
存放传输的数据
{
'name':"name"
'state':true
}
对于签名令牌,此信息虽然可以防止篡改,但任何人都可以读取。除非加密,否则不要将敏感信息放入到Payload或Header元素中。
Payload中放传输的信息,用户信息等用于传输的信息。Playload部分的JSON使用base64编码加密,形成JWT的第二部分。
eyJzdWIiOiJ0b2tlbl9kZW1vIiwiaXNzIjoiU0VSVklDRSIsIm5hbWUiOiJ4eXgiLCJleHAiOjE2Mjk1Mzk0MzMsImlhdCI6MTYyOTQ1MzAzMywidXNlcklkIjoyMX0
Signature(签名)
这个部分需要base64加密后的header和base64加密后的payload使用.
连接组成的字符串,然后通过header中声明的加密方式进行secret
组合加密,然后就构成了jwt的第三部分
如:HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
将这三部分用.连接,组成了一个JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0b2tlbl9kZW1vIiwiaXNzIjoiU0VSVklDRSIsIm5hbWUiOiJ4eXgiLCJleHAiOjE2Mjk1Mzk0MzMsImlhdCI6MTYyOTQ1MzAzMywidXNlcklkIjoyMX0.91uTZ1O7Pt_st_UKBlTseMJe3ZlSu027mrv4Admo1u8
6、JWT优缺点
优点:
①. 可扩展性好 应用程序分布式部署的情况下,Session需要做多机数据共享,通常可以存在数据库或者Redis里面。而JWT不需要。 ②. 无状态 JWT不在服务端存储任何状态。RESTful API的原则之一是无状态,发出请求时,总会返回带有参数的响应,不会产生附加影响。用户的认证状态引入这种附加影响,这破坏了这一原则。另外JWT的载荷中可以存储一些常用信息,用于交换信息,有效地使用 JWT,可以降低服务器查询数据库的次数。
缺点:
① 安全性:由于JWT的payload是使用Base64编码的,并没有加密,因此JWT中不能存储敏感数据。而Session的信息是存在服务端的,相对来说更安全。 ② 性能:JWT太长。由于是无状态使用JWT,所有的数据都被放到JWT里,如果还要进行一些数据交换,那载荷会更大,经过编码之后导致JWT非常长,Cookie的限制大小一般是4k,cookie很可能放不下,所以JWT一般放在LocalStorage里面。并且用户在系统中的每一次Http请求都会把JWT携带在Header里面,Http请求的Header可能比Body