Jwt使用笔记
1|0一、什么是JWT
JWT全称 Json·Web·Token,通俗地讲,也就是通过JSON形式作为Web应用中的令牌,用于在各⽅之间安全地将信息作为JSON对象传输,在数据传输地过程中还可以完成数据加密、签名等相关处理,是目前最流⾏的跨域身份解决⽅案。
2|0二、JWT能做什么
2|11.授权(使用JWT最常见的方案)
一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由、服务和资源。单点登录是当今广泛使用JWT的一项功能,因为它的开销很小并且可以在不同的域中轻松使用。(即JWT能过够实现跨域)
2|22.信息交换
JWT是在各方之间安全地传输信息地好方法。因为可以对JWT进行签名(比例使用公钥/私钥对),所以可以确保发件人是他们所说的人。
3|0三、为什么是JWT
3|1基于传统的session认证
1.认证方式 HTTP协议是⽆状态的,也就是说,如果我们已经认证了⼀个⽤户,那么他下⼀次请求的时候,服务器不知道我是谁,我们必须再次认证。 传统的做法是将已经认证过的⽤户信息存储到服务器上,⽐如session。⽤户下次请求的时候带sessionId,然后服务器检查⽤户是否已经认证过。 2.暴露问题 这种基于服务器的身份认证⽅式存在⼀些问题: 1.Seesions:每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。通常而言session都是保存在内存中,当越来越多的用户发请求时,内存的开销也会不断增加。 2.可扩展性:由于sessions 存放在服务器内存中,这意味着用户下次请求还必须在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡的能力,这也意味着限制了应用的扩展能力。 3.CORS (跨域资源共享):当我们扩展应用程序,让数据能够从不同设备上访问时,跨域资源的共享会是一个让人头疼的问题,不方便集群应用。 4.CSRF (跨站请求伪造):因为是基于cookie来进行用户识别的,cookie如果被截获,用户就很容易受到跨站请求的攻击。
补充: 1.那么究竟什么是跨站请求伪造呢?简单地说就是用你的身份去发送一些对你不友好的请求。 举个简单的例子: 小壮登录了某网上银行,他来到了网上银行的帖子区,看到一个帖子下面有一个链接写着“科学理财,年盈利率过万”,小壮好奇的点开了这个链接,结果发现自己的账户少了10000元。这是这么回事呢?原来黑客在链接中藏了一个请求,这个请求直接利用小壮的身份给银行发送了一个转账请求,也就是通过你的 Cookie 向银行发出请求。 导致这个问题很大的原因就是: Session 认证中 Cookie 中的 session_id 是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。 那么为什么token不存在这种问题呢? 一般情况下我们使用 JWT 的话,在我们登录成功获得 token 之后,一般会选择存放在 local storage 中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 token,这样就不会出现 CSRF 漏洞的问题。因为,即使有个你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 token 的,所以这个请求将是非法的。(网上找的,个人有点不理解,坑待填) 2.注意区分跨站请求伪造与数字签名(个人理解,可能不对,只是看到CSRF,就突然想到了数字签名) 跨站请求伪造是用你的身份去发送一些对你不友好的请求,这个是基于请求信息上的攻击。而数字签名是防止别人伪造自己的身份发送信息,这个是基于身份验证上的。
3|2基于JWT认证
1.认证流程 2.jwt优势 ⽆状态和可拓展性:Token 存储在客户端,完全⽆状态,可拓展,特别适用于分布式微服务。我们的负载均衡器可以将⽤户传递到任意服务器,因为在任何地⽅都没有状态或会话信息。
简洁:每次请求的时候token都会被发送,可以作为请求参数发送,可以放在请求头⾥⾯发送,也可以放在cookie⾥⾯被发送,因为数据量小,传输速度也很快。
自包含:负载中包含了所有用户所需要的信息,避免了多次查询数据库。
补充:我刚开始不太理解为什么JWT在浏览器本地存储比session在服务器端存储在负载方面要好,这里我给出自己的理解: 服务器端保存所有的用户的数据,所以服务器端的开销较大,而浏览器端保存则把不同用户需要的数据分布保存在用户各自的浏览器中。
4|0四、JWT的结构是什么?
jwt由三部分组成,他们之间⽤圆点(·)连接,这三部分分别是: 1.标头Header 2.有效负载Payload 3.签名Signature
Header由两部分信息组成: type:声明类型,这⾥是jwt alg:声明加密的算法 通常直接使⽤ HMAC SHA256
Payload就是存放有效信息的地⽅(不强制) iss: jwt签发者 sub: jwt所⾯向的⽤户 aud: 接收jwt的⼀⽅ exp: jwt的过期时间,这个过期时间必须要⼤于签发时间 nbf: 定义在什么时间之前,该jwt都是不可⽤的 iat: jwt的签发时间 jti: jwt的唯⼀身份标识,主要⽤来作为⼀次性token,从⽽回避重放攻击 claim:jwt存放信息的地⽅
Signature就是签名信息 签名目的: 最后一步签名的过程,实际上是对头部以及负载内容进行签名,防止内容被篡改。
因此,⼀个典型的JWT看起来是这个样⼦的: xxxxxxxx·yyyyyyyyyy·zzzzzzzzzzz
5|0五、使用JWT
5|11.引入依赖
5|22.生成token
生成结果: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDQwMjY5ODUsInVzZXJuYW1lIjoi5byg5LiJIn0.cZf24DSxSX4LR-2Z6pTKufAg6kOSJiMANzuXgKz2BrE
5|33.根据令牌和签名解析数据
6|0六、封装工具类
7|0七、整合springboot
7|10.搭建springboot+mybatis+jwt环境
引入依赖
编写配置
7|21.开发数据库
这里采用最简单的表结构验证JWT使用 (这里我偷下懒,没有写sql语句,直接用navicat建表了)