前言
JWT和OAuth2.0没有可比性,是两个完全不同的东西。
JWT是一种认证协议,提供了一种用于发布接入令牌(Access Token),并对发布的签名接入令牌进行验证的方法。SSO私钥加密token。应用端公钥解密token,
OAuth2.0是一种授权框架,提供了一套详细的授权机制(指导)。用户或应用可以通过公开的或私有的设置,授权第三方应用访问特定资源。
一、JWT
1、JWT格式
一个JWT包含3个部分:
头部Header:可存放签名的类型
数据Payload:可存放用户数据和有效期,Payload的内容在接收者端是通过签名(Signature)来校验的。
签名Signature:使用密钥对Header和Payload数据进行加密生成签名。
JWT为了便于http传输,3个部分需再进行Base64Url编码后用.
进行关联,格式如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
JWT真正的好处是让颁发JWT token的认证服务器和校验JWT token的应用服务器可以完全分开。
那签名是如何完成认证功能的呢,且看:
- 用户向认证服务器提交用户名和密码,认证服务器也可以和应用服务器部署在一起,但往往是独立的居多;
- 认证服务器校验用户名和密码组合,然后创建一个JWT token,token的Payload里面包含用户的身份信息,以及过期时间戳;
- 认证服务器使用密钥对Header和Payload进行签名,然后发送给客户浏览器;
- 浏览器获取到经过签名的JWT token,然后在之后的每个HTTP请求中附带着发送给应用服务器。经过签名的JWT就像一个临时的用户凭证,代替了用户名和密码组合,之后都是JWT token和应用服务器打交道了;
- 应用服务器检查JWT签名,确认Payload确实是由密钥拥有者签过名的;
- Payload身份信息代表了某个用户;
- 只有认证服务器拥有私钥,并且认证服务器只把token发给提供了正确密码的用户;
- 因此应用服务器可以认为这个token是由认证服务器颁发的也是安全的,因为该用户具有了正确的密码;
- 应用服务器继续完成HTTP请求,并认为这些请求确实属于这个用户;
2、签名和验签
对于JWT,签名方式有很多种,这里我们主要了解HS256和RS256。
HS256
HS256 使用同一个「secret_key」进行签名与验证(对称加密)。一旦 secret_key 泄漏,就毫无安全性可言了。
- 如何使用哈希函数生成签名?
我们拿到Header、Payload外,还要加上一个密码,将这三个输入值一起哈希。输出结果是一个SHA-256 HMAC或者基于哈希的MAC。如果需要重复生成,则需要同时拥有Header、Payload和密码才可以。这也意味着,哈希函数的输出结果是一个数字签名,因为输出结果就表示了Payload是由拥有密码的角色生成并加签了的,没有其它方式可以生成这样的输出值了。
- 如何校验JWT签名?
当我们的服务接收到HS256签名的JWT时,我们需要使用同样的密码才能校验并确认token里面的Payload是否有效。为了验证签名,我们只需要将JWT Header和Payload以及密码通过哈希函数生成结果。JWT的接收者需要拿到和发送者一样的密码值。如果我们得到的哈希结果和JWT第三部分的签名值是一致的,则说明有效,可以确认发送者确实和接收者拥有相同的密码值。
- 公式如下:
签名Signature=Header+Payload+一个密码 进行SHA-256哈希;再进行Base64Url编码(主要方便url上传输)。
验签: Header+Payload+一个密码 进行SHA-256哈希;和JWT的签名Signature对比。
RS256
RS256 是使用 RSA 私钥进行签名,使用 RSA 公钥进行验证。相比HS256更加安全。
使用RS256我们同样需要生成一个MAC,其目的仍然是创建一个数字签名来证明一个JWT的有效性。只是在这种签名方式中,我们将创建token和校验token的能力分开,只有认证服务器具备创建的能力,而应用服务器,具备校验的能力。
这样,我们需要创建两个密钥而不是一个:
仍然需要一个私钥,不过这次它只能被认证服务器拥有,只用来签名JWT。
私钥只能用来签名JWT,不能用来校验它。
第二个密钥叫做公钥(public key),是应用服务器使用来校验JWT。
公钥可以用来校验JWT,但不能用来给JWT签名。
公钥一般不需要严密保管,因为即便黑客拿到了,也无法使用它来伪造签名。
- 公式如下:
签名Signature=Header+Payload 进行SHA-256哈希,再使用私钥对哈希值进行签名;再进行Base64Url编码(主要方便url上传输)。
验签: Header+Payload进行SHA-256哈希;使用公钥签名Signature进行解密,解密后的值和前面哈希值对比。
RSA的两点基本原理
- 私钥加密,持有私钥或公钥才可以解密
- 公钥加密,持有私钥才可解密
RSA公钥、私钥加密的使用场景
公钥和私钥都可以用于加解密操作,用公钥加密的数据只能由对应的私钥解密,反之亦然。虽说两者都可用于加密,但是不同场景使用不同的密钥来加密,规则如下:
私钥用于签名、公钥用于验签
签名和加密作用不同,签名并不是为了保密,而是为了保证这个签名是由特定的某个人签名的,而不是被其它人伪造的签名,所以私钥的私有性就适合用在签名用途上。
私钥签名后,只能由对应的公钥解密,公钥又是公开的(很多人可持有),所以这些人拿着公钥来解密,解密成功后就能判断出是持有私钥的人做的签名,验证了身份合法性。
公钥用于加密、私钥用于解密,这才能起到加密作用
因为公钥是公开的,很多人可以持有公钥。若用私钥加密,那所有持有公钥的人都可以进行解密,这是不安全的!
若用公钥加密,那只能由私钥解密,而私钥是私有不公开的,只能由特定的私钥持有人解密,保证的数据的安全性。
二、OAuth2.0
OAuth2 有4种授权模式, 其中的access code授权码模式在实现时可以使用JWT生成code, 也可以不用. 它们之间没有必然的联系;
-
示例1:QQ音乐使用微信登录
-
示例2:口碑使用支付宝登录
三、应用场景
- OAuth2用在使用第三方账号登录的情况(比如使用weibo, qq, github登录某个app)
- JWT是用在前后端分离, 需要简单的对后台API进行保护时使用.(前后端分离无session, 频繁传用户密码不安全)
来源地址:https://blog.csdn.net/sssssooo/article/details/128509302