登录 token 前后端分离之JWT用户认证.txt
参考:https://www.jianshu.com/p/180a870a308a
https://blog.csdn.net/qq_39314932/article/details/88356747
https://segmentfault.com/a/1190000019938678
一、Json Web Token(JWT)
适用场景
1、用于向Web应用传递一些非敏感信息。例如完成加好友、下订单的操作等等。
2、用于设计用户认证和授权系统。
3、实现Web应用的单点登录。
实例场景
在A用户关注了B用户的时候,系统发邮件给B用户,
并且附有一个链接“点此关注A用户”。
链接的地址:
https://your.awesome-app.com/make-friend/?from_user=B&target_user=A。
让B用户不用登录就可以完成这个操作。
1.1.JWT 是一个开放标准(RFC 7519),
它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。
JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名。
它具备两个特点:
简洁(Compact)
可以通过URL, POST 参数或者在 HTTP header 发送,因为数据量小,传输速度快
自包含(Self-contained)
负载中包含了所有用户所需要的信息,避免了多次查询数据库
1.2.JWT 组成
Header(头部),Payload(负载),Signature(签名)。
1.2.1.Header
描述 JWT 最基本的信息,例如,其类型及签名所用的算法等。
通常如下:
{
"alg": "HS256",
"typ": "JWT"
}
注:
alg,签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);
typ,令牌(token)的类型(type),JWT令牌统一写为JWT。
用途:将 header 对象使用 Base64URL 方法编码成字符串,组成 JWT 结构的第一部分。
1.2.2.Payload
用来存放实际需要传递的数据。JWT规定了7个官方字段,供选用。
例子:
{
// 7个官方字段
"jti": "1111", // JWT ID:编号
"iss": "a.com", // issuer:签发人
"iat": "xxx", // Issued At: 签发时间
"nbf": "xxx", // Not Before:生效时间
"exp": "1d", // expiration time:(必须设置)
"sub": "test", // subject: 主题
"aud": "xxx", // audience: 受众
// 可以定义私有字段
"name": "John Doe",
"admin": true
}
{
"iss": "John Wu JWT",
"iat": 1441593502,
"exp": 1441594722,
"aud": "www.example.com",
"sub": "jrocket@example.com",
"from_user": "B",
"target_user": "A"
}
注:
iss (issuer) 该JWT的签发者
exp (expiration time) 过期时间(为一个UNIX时间戳)
sub (subject) 该JWT所面向的用户
aud (audience): 接受该JWT的一方
nbf (Not Before) 生效时间
iat (Issued At) 签发时间
jti (JWT ID) 编号
它也使用 Base64URL 方法编码成字符串,组成 JWT 结构的第二部分。
注:JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。
1.2.3.Signature(签名)
对前两部分的签名,防止数据被篡改。
需要指定一个密钥(secret)。
采用的公式:
Signature = header 中的签名算法(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret)
JWT = Base64(Header) + "." + Base64(Payload) + "." + $Signature
将上面的两个编码后的字符串用点号连接在一起(头部在前),就形成了,例如:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0
最后,我们将上面拼接完的字符串用 HS256 算法进行加密。
在加密的时候,我们还需要提供一个密钥(secret)。
如果我们用 mystar 作为密钥的话,那么就可以得到我们加密后的内容:
rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
这一部分又叫做签名。
后将这一部分签名也拼接在被签名的字符串后面,
我们就得到了完整的 JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
于是,我们就可以将邮件中的URL改成:
https://your.awesome-app.com/make-friend/?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
然后使用 header 中指定的签名算法(HS256)进行签名。
1.2.4.签名的目的
最后一步签名的过程,实际上是对头部、负载内容进行签名,防止内容被窜改。
如果有人对头部以及负载的内容解码之后进行修改,再进行编码,
最后加上之前的签名组合形成新的JWT的话,
那么服务器端会判断出新的头部和负载形成的签名和JWT附带上的签名是不一样的。
如果要对新的头部和负载进行签名,在不知道服务器加密时用的密钥的话,得出来的签名也是不一样的。
1.3.JWT 使用
1.3.1.首先,前端通过Web表单将自己的用户名和密码发送到后端的接口。
这一过程一般是一个HTTP POST请求。
建议的方式是通过SSL加密的传输(https协议),从而避免敏感信息被嗅探。
1.3.2.后端验证成功,根据上述方法生成 token,并返回给前端。
1.3.3.前端可以将返回的结果保存在localStorage或sessionStorage上,
退出登录时前端删除保存的JWT即可。
1.3.4.前端在每次请求时将JWT放入HTTP Header中的Authorization位。(解决XSS和XSRF问题)
1.3.5.后端检查是否存在,如存在,验证JWT的有效性。
例如,检查签名是否正确;检查Token是否过期;检查Token的接收方是否是自己(可选)。
1.3.6.验证通过后,后端使用JWT中包含的用户信息进行其他逻辑操作,返回相应结果。
1.4.JWT 的优势
JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。
除了用户id之外,还可以存储其他的和用户相关的信息,
例如该用户是否是管理员、用户所在的分组等。
虽说JWT方式让服务器有一些计算压力(例如加密、编码和解码),
但是这些压力相比磁盘存储而言可能就不算什么了。
具体是否采用,需要在不同场景下用数据说话。
1.5.总结
JWT的主要作用:
(一)可附带用户信息,后端直接通过JWT获取相关信息。
(二)使用本地保存,通过HTTP Header中的 Authorization 位提交验证。
get 请求:可以放在 HTTP 请求头 Authorization 字段中,也可以拼接在url的后面。
post 请求:可以放在请求数据里。
但其实关于JWT存放到哪里一直有很多讨论,有人说存放到本地存储,有人说存 cookie。
个人偏向于放在本地存储。
1.6.JWT 的几个特点
(1)JWT默认是不加密,但也是可以加密的。生成原始Token以后,可以用密钥再加密一次。
(2)JWT不加密的情况下,不能将秘密数据写入JWT。
发送 JWT,要使用 https,不使用 https 的时候,JWT里面不要写入秘密数据。
(3)JWT不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
(4)JWT的最大缺点是,由于服务器不保存session状态,
因此无法在使用过程中废止某个token,或者更改token的权限。
也就是说,一旦JWT签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
(5)JWT本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。
为了减少盗用,JWT 的有效期应该设置得比较短。
对于一些比较重要的权限,使用时应该再次对用户进行认证。
(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。
(7)便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。
(8)它不需要在服务端保存会话信息,所以它易于应用的扩展。
登录 token 前后端分离之JWT用户认证.txt
最新推荐文章于 2022-08-30 14:29:18 发布