JWT学习笔记

JWT(JSON Web Token)
一、JWT的结构
JWT包含了使用 . 连接的三个部分组成,他们分别是Header标头、payload负载、signature签名:
Header
在header中通常包含了两部分:token类型和采用的加密算法。
{ "alg": "HS256", "typ": "JWT" }
接下来对这部分内容使用 Base64Url 编码组成了JWT结构的第一部分。
Payload
Token的第二部分是负载,它包含了claim, Claim是一些实体(通常指的用户)的状态和额外的元数据,有三种类型的claim: reserved, public 和 private.
  • Reserved claims: 这些claim是JWT预先定义的,在JWT中并不会强制使用它们,而是推荐使用,常用的有 iss(签发者), exp(过期时间戳), sub(面向的用户), aud(接收方), iat(签发时间)。
  • Public claims:根据需要定义自己的字段,注意应该避免冲突
  • Private claims:这些是自定义的字段,可以用来在双方之间交换信息
负载使用的例子:
{ "sub": "1234567890", "name": "John Doe", "admin": true }
上述的负载需要经过Base64Url编码后作为JWT结构的第二部分。
Signature
创建签名需要使用编码后的header和payload以及一个密钥(密钥建议不要直接写在代码里,可以放到统一的配置中心,且不要轻易对外公开),使用header中指定签名算法进行签名。例如如果希望使用HMAC SHA256算法,那么签名应该使用下列方式创建:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
签名用于验证消息的发送者以及消息是没有经过篡改的。
二、首先为什么使用JWT?
就不得不提传统的Session认证的弊端,首先我们知道http协议本身是无状态的,因此当用户通过网页将自己的用户名和密码传递给服务器进行认证的时候,服务器认证成功之后并不会保存这次认证结果的,这就导致当我们下次再次请求时候必须还要进行登陆状态的认证,但是这个时候服务器并没有保存上次的认证结果,服务器并不知道那个用户是登陆成功的,所以因为这个情况,session认证机制就要求我们在首次登陆成功之后需要在服务器内存中存放一份登陆信息,同时响应给客户端结果让其本地生成cookie,这样下次发起请求的时候,就可以携带这个cookie,去与服务器中的session登陆信息进行比对就知道发起这次请求的用户是否是登陆状态了,这就是session认证机制,
那么session认证机制的问题有哪些呢:
1、这个机制随着用户体量的增加,服务器中存储的用户登陆信息会越来越多,会增加服务器的压力;2、在当今微服务大行其道的时候,多数服务器都是采用的集群的方式进行部署的,这就要求集群中的session必须实现共享,这就对服务器的负载均衡带来了一定的麻烦;
3、对于前后端分离的项目,用户请求从浏览器发送通常也不是直接就到达服务器的而是层层的中间件nginx进行转发,session机制不太适用;
4、session机制对于跨域的情况很难去解决,cookie不支持跨域,就不是很友好了,对于单点登录不适用;
5、对于手机端,session机制也是不适用的,主要是手机端没有cookie;
6、session认证本质基于cookie,所以如果cookie被截获,用户很容易收到跨站请求伪造攻击。并且如果浏览器禁用了cookie,这种方式也会失效;
三、JWT认证的优势
对比传统的session认证方式,JWT的优势是:
1、简洁:JWT Token数据量小,传输速度也很快;
2、因为JWT Token是以JSON加密形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支持;
3、不需要在服务端保存会话信息,也就是说不依赖于cookie和session,所以没有了传统session认证的弊端,特别适用于分布式微服务;
4、单点登录友好:使用Session进行身份认证的话,由于cookie无法跨域,难以实现单点登录。但是,使用token进行认证的话, token可以被保存在客户端的任意位置的内存中(一般情况是放在请求头中),不一定是cookie,所以不依赖cookie,不会存在这些问题;
5、适合移动端应用:使用Session进行身份认证的话,需要保存一份信息在服务器端,而且这种方式会依赖到Cookie(需要 Cookie 保存 SessionId),所以不适合移动端;
6、无需考虑CSRF:由于不再依赖cookie,所以采用token认证方式不会发生CSRF,所以也就无需考虑CSRF的防御;
7、自保含,jwt的负载中可以包含了所有用户所需要的信息,避免了多次查询数据库。
四、JWT流程
通俗地说,JWT的本质就是一个字符串,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个JWT token,并且这个JWT token带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。JWT的认证流程如下:
 
1、首先,前端通过Web表单将自己的用户名和密码发送到后端的接口,这个过程一般是一个POST请求。建议的方式是通过SSL加密的传输(HTTPS),从而避免敏感信息被嗅探
2、后端核对用户名和密码成功后,将包含用户信息的数据作为JWT的Payload,将其与JWT Header分别进行Base64编码拼接后签名,形成一个JWT Token,形成的JWT Token就是一个如同lll.zzz.xxx的字符串
3、后端将JWT Token字符串作为登录成功的结果返回给前端。前端可以将返回的结果保存在浏览器中,退出登录时删除保存的JWT Token即可
4、前端在每次请求时将JWT Token放入HTTP请求头中的Authorization属性中(解决XSS和XSRF问题)
5、后端检查前端传过来的JWT Token,验证其有效性,比如检查签名是否正确、是否过期、token的接收方是否是自己等等
6、验证通过后,后端解析出JWT Token中包含的用户信息,进行其他逻辑操作(一般是根据用户信息得到权限等),返回结果。
 
五、JWT应用场景
1、身份认证在这种场景下,一旦用户完成了登陆,在接下来的每个请求中包含JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在单点登录(SSO)中比较广泛的使用了该技术。
2、信息交换在通信的双方之间使用JWT对数据进行编码是一种非常安全的方式,由于它的信息是经过签名的,可以确保发送者发送的信息是没有经过伪造的。

 

------这里只记录概念,具体的代码可参考API文档

posted @ 2022-03-30 09:53  悠悠南山下  阅读(61)  评论(0编辑  收藏  举报