目录
1、什么是JWT
2、JWT能做什么
3、为什么是JWT
基于传统的Session认证
基于JWT的认证
4、JWT的结构是什么
5、使用JWT
总结
JWT官网地址:https://jwt.io/introduction/
官方解释:JWT是Java Web Token的首字母简写,它定义了一个紧凑的,自包含的方式,用于在各方之间以Json对象安全的传输信息。此信息可以验证和信任,因为它是数字签名。jwt可以使用签名算法进行签名。
通俗解释:JWT(Java Web Token)就是通过Json形式作为Web应用中的令牌,用于在各方之间安全的将信息作为Json对象进行传输,在数据传输的过程中,还可以完成数据的加密,签名等管理。
(所谓令牌,其实就是权力的象征。比如在古代,大将军会拿着令牌号召军队东征西战。这个军队是否让将军掌管,将军得有令牌才可以。类比,服务器端的接口要能被用户访问,用户得有服务端一样的令牌才能访问服务端的接口。)
JWT有两方面的作用:1、授权 2、信息交换
1、授权:JWT最常用的作用就是授权认证。一旦用户的登录,前提是输入正确的用户名和密码,当用户登录成功后,服务端提供给客户端一个token令牌(签名已经详细的说明了令牌的作用),拿到令牌的用户就有了访问服务端接口的权利,每次客户端带着令牌访问服务端数据的时候,服务端就会检查这个令牌有没有过期,预检查是否正确(后面会细讲:将请求头和payload和用户带来的签名进行合并,合并的结果检查是否比篡改),每个后续请求将包含JWT,从而允许用户访问允许的路由或者是接口,服务和资源。单点登录是当今广泛使用的JWT的一项功能,因为JWT的开销很小并且可以在不同域中使用。
2、信息交换:JWT是各方之间安全传输信息的好办法。因为可以对JWT进行签名(例如公钥、私钥对),确保信息安全。签名是使用标头和有效负载进行计算的,可以验证内容是否被修改。
小结:
前端系统怎么访问后端系统的接口呢?
每次前端向后端传一个令牌,如果这个令牌是后端需要放行的这个令牌。允许访问后端的数据。如果前端的这个令牌不是后端是认识的,被篡改了,或者过期,那么就拒绝访问。
JWT可以在系统之间进行数据的传递,A系统向B系统传递数据,A系统通过JWT传递数据。传递的过程中也可以读数据进行签名或者加密。B拿到数据后,还可以验证签名查看这个数据是否被中间的过程篡改了。拿到的数据是否为A系统给B发的原数据。可以在B系统那儿进行签名校验。在A系统进行秘钥加密签名,如果在B系统那里能秘钥解密,如果发现A B 系统的签名如果能对上,说明过程中没有任何人进行篡改。如果B收到的是篡改的信息,那么B就会拒绝此信息。
我们知道,http协议是一种无状态的协议,这就意味着,如果用户向我们提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要一次用户的认证才行,因为根据http协议,我们并不知道是哪个用户发出的请求,所以为了让我们的应用是被是哪一个请求发出的请求,我们只能在用户端存储一份用户的信息,这个信息会在响应时候传递给浏览器,将sessionID保存在Cookie中,以便下次请求发送给我们的应用,这样通过验证Cookie中的sessionid来识别是哪一个用户的登录,sessionid在服务端进行验证,sessionid是对用户的记录。具体详细了解Session和Cookie,请访问:https://blog.csdn.net/Sunshineoe/article/details/109288143
打开你的网页,按F12开发者模式,在Header中找到Cookie。
在postman后端验证
基于传统的Session认证的暴露的问题:
1、每个用户经过我们的应用认证之后,我们的应用都会在服务端做一次记录,也就是sessionid,以方便用户下次请求的鉴别,通常session都是保存在内存中的,也就是服务器中,而随着认证的用户增多,服务端的开销显然会增大。
2、用户认证之后,服务端做认证登录,如果认证的记录保存在内存中的话,这就意味着下次用户的访问必须要请求这台服务器,这样才能拿到授权的资源。意思就是每次访问都需访问内存的资源。这样在分布式上,限制了负载均衡的能力,限制了应用的扩展的能力。
3、因为是基于Cookie来进行用户识别的,cookie如果被截获,用户就会很容易受到跨站请求伪造而受到攻击。
4、在前后端分离系统中暴露的问题更加显著。
在数据量大的时候,用户通常一次请求就要转发好多次。如果用session每次携带sessionid到服务器,服务器还要查询用户信息。但是如果同时有很多用户访问,就会给服务器带来很大的负担。cookie容易被截获,容易被攻击。还有sessionid是一个特征值,所带的信息并不够丰富,不容易进行扩展,不方便集群。
知识补充:
负载均衡:负载就是承载的能力,具体的说就是用户的访问请求和计算机的工作任务。意思就是将负载平衡、分摊到多个操作系统单元执行,解决的是高性能,扩展性的终极解决方案。防止资源分配不均匀,资源浪费。
JWT是基于客户端的令牌存储,存储的是JWT的本地存储,节省了服务器端内存中资源。
认证的过程:用户认证通过输入正确的用户名和密码进行登录。登录成功后,服务端认证会生成一个token,服务端会把令牌响应给客户端,客户端会在本地保存这个令牌。之后客户端访问服务端的接口获取数据的时候,服务端在令牌那边进行验证。服务器端将用户的id等用户信息作为JWT的负载(payload),将其与头部分别进行64位编码拼接后进行签名,形成一个JWT的token,服务器端验证这个是合法的令牌,将会允许调用服务器端的接口。如果不是合法的令牌,则出现异常或者提示信息。JWT内容包含丰富。JWT令牌都是基于浏览器客户端的。JWT有三部分构成的一个字符串,header.payload.singurator,即头部、负载、签名。
客户端将每次请求放在了HTTP中的Header中授权Authorization中。
服务端首先检查JWT是否存在,如果存在,则继续验证JWT的有效性,检查签名是否正确;检查token是否过期;检查token信息的正确性。验证成功后,也就是用户有权限对服务端的数据进行操作。
1、JWT令牌的组成
① 标头(Header)
② 有效载荷(PayLoad)
③ 签名(Signature)
因此JWT通常组成:xxxxxx.yyyyyy.zzzz,Header.PayLoad.Signature
<1>Header
标头通常由两部分组成:令牌的类型即JWT、使用的签名算法比如HAMC SHA256加密算法,使用编码Base64编码组成JWT的头部分。格式如下:
{
"alg":"HS256",
"typ":JWT
}
<2>PayLoad
令牌的第二部分是有效负载,其中包含了声明,对用户的信息进行声明。同样的使用64位编码组成JWT的第二部分。
JWT是自包含想要的token信息,将自身想要的用户信息放到(负载)paylaod里面进行保存,比如登录成功后的payload可能指向用户id,用户名,权限等信息,这些信息都放在了负载里面,存储的格式都是JSON的格式
{
"sub":"12121334",
"name":"admin",
}
<3>Signature
签名两个部分都是使用Base64位进行的编码,Signature需要使用编码后的header,payload,以及我们提供的一个秘钥,然后使用header指定签名算法进行签名Signature,篡改其中的任何一个header,payload中的任何一个,以及签名算法,最后签名Signature都不会是正确的,和服务器端提供的签名不同。
签名的目的:
实际上是对头部以及负载内容进行签名,防止内容被修改。
签名的验证:签名的验证看上图,上面的三个方框代表的是:Header.PayLoad.Signature
当用户登录成功的时候,服务端电信通过①②生成签名,传递给用户。用户可以得到服务器端生成的①②+签名信息。当用户在token未过期的情况下,用户拿到这个令牌再次请求服务端的接口数据。这个时候服务器端会有一个先验的过程,服务器端先拿服务器生成的签名和客户端带来的token中的①②也就是header.payload进行验证,如果客户端带来的①②生成的签名和服务器端之前的签名一样,那么校验成功!如果在客户端在请求过程中出现被篡改①,②,signature中任何一个的话,那么生成的签名就不是原来的服务器端的签名,那么验证失败,服务器端就会拒绝客户端访问接口。
下面是加密后的JWT
<4>token时间过期的问题
token服务端的认证是有有效期的。当过期了怎么办?
于是Refresh Token 被创造出来了,服务器不需要刷新token,一旦token过期,服务器就会反馈给前端,前端使用Refresh Token向服务端申请一个全新的Token继续使用。在这个过程中,服务端只需要对客户端寻求刷新的Refresh Token的有效期进行一次检查,大大减少了更新有效期的操作。当然Refresh Token也是有效期的,有效期时间长了点,以天为单位。
当然了,Refresh Token过期了,就需要用户名和密码进行登录了。
JWT是权限认证的好的办法。有token过期时间认证,如果没时间没有过期,继续进行签名认证。用户一般将token存储在HTTP头部,payload信息里面存储的是用户的相关信息。header里面的签名算法生成签名Signature,这样三部分就形成了。签名验证保证了信息的安全性。服务器端的数据一般使用的是拦截器进行拦截访问。
理论的内容大概那么多,使用的话需具体代码实现。