登录 token 前后端分离之JWT用户认证.txt

登录 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)它不需要在服务端保存会话信息,所以它易于应用的扩展。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值