OAuth2认证和jwt机制

烈酒焚心 提交于 2020-11-26 04:24:28

一、OAuth2认证

OAuth2是一个关于授权的开放标准,核心思路是通过各类认证手段(具体什么手段OAuth2不关心)认证用户身份,并颁发token(令牌),
使得第三方应用可以使用该token(令牌)在限定时间、限定范围访问指定资源。

OAuth2相关概念:

资源所有者(resources owner):拥有被访问资源的用户
客户端/第三方应用(client):第三方应用,获取资源服务器提供的资源
授权服务器(authorization server):认证服务器,提供授权许可code、令牌token等
资源服务器(resource server):资源服务器,拥有被访问资源的服务器,需要通过token来确定是否有权限访问

OAuth2几种模式:
获取令牌的方式主要有四种,分别是授权码模式、隐式授权码模式(简单模式)、密码模式和客户端模式。

1)授权码模式(authorization code)
这种模式是最安全的OAuth2的授权模式。设计了auth code,通过这个code再获取token,最后通过token获取资源。支持refresh token。

应用场景:
各大应用内的qq,微信,微博登录等。比如某应用内的qq登录,过程如下:
a.用户点击qq登录,会先跳转到qq登录页面,这时请求已经跳转到qq服务器了,然后用户输入账号或者扫码登录,这时所有请求都在qq服务器完成。
b.用户正确登录后,qq服务器返回用户的code给第三方应用,然后第三方应用再使用code去授权服务器请求获取token。(这一步用户不可见)
c.第三方应用获取到token后,再使用token获取用户的qq名称,头像等信息。

优缺点:
优点:用户可以控制自身的一些权限是否给第三方,第三方只能获取到用户临时产生的一个访问的code,安全性。
缺点:认证过程繁琐。

2)隐式授权码模式/简单模式(implicit)
和授权码模式类似,只不过少了获取code的步骤,是直接获取令牌token的,适用于公开的浏览器单页应用,令牌直接从授权服务器返回,不支持刷新令牌,且没有code安全保证,令牌容易因为被拦截窃听而泄露。
不支持refresh token

3)密码模式(resource owner password credentials)
这种模式是最不推荐的,因为client可能存了用户密码
这种模式主要用来做遗留项目升级为oauth2的适配方案
当然如果client是自家的应用,也是可以
支持refresh token

4)客户端模式(client credentials)
这种模式直接根据client的id和密钥即可获取token,无需用户参与
这种模式比较合适消费api的后端服务,比如拉取一组用户信息等
不支持refresh token,主要是没有必要

二、JWT机制

JWT概念:

JWT全称为Json Web Token,随着微服务架构的流行而越来越火,号称新一代的认证技术。
OAuth2中使用token验证用户登录合法性,但token最大的问题是不携带用户信息,资源服务器无法在本地进行验证,每次对于资源的访问,资源服务器都需要向认证服务器发起请求,一是验证token的有效性,二是获取token对应的用户信息。如果有大量的此类请求,无疑处理效率是很低,且认证服务器会变成一个中心节点,这在分布式架构下很影响性能。
JWT就是在这样的背景下诞生的,从本质上来说,jwt和OAuth2没有可比性。普通的oauth2颁发的就是一串随机hash字符串,本身无意义,而jwt使用一种特殊格式的token,token是有特定含义的,分为三部分:
-头部Header
-载荷Payload
-签名Signature
这三部分均用base64进行编码,并使用.进行分隔。一个典型的jwt格式的token类似xxxxx.yyyyy.zzzzz。

jwt其实并不是什么高深莫测的技术,相反非常简单。认证服务器通过对称或非对称的加密方式利用payload生成signature,并在header中申明签名方式,仅此而已。通过这种本质上极其传统的方式,jwt可以实现分布式的token验证功能,即资源服务器通过事先维护好的对称或者非对称密钥(非对称的话就是认证服务器提供的公钥),直接在本地验证token,这种去中心化的验证机制非常适合分布式架构。jwt相对于传统的token来说,解决以下两个痛点:
1、通过验证签名,对于token的验证可以直接在资源服务器本地完成,不需要连接认证服务器;
2、在payload中可以包含用户相关信息,这样就轻松实现了token和用户信息的绑定;
如果认证服务器颁发的是jwt格式的token,那么资源服务器就可以直接自己验证token的有效性并绑定用户,这无疑大大提升了处理效率且减少了单点隐患。

适用场景:
一次性的身份认证、api的鉴权等,这些场景能充分发挥jwt无状态以及分布式验证的优势。

不适用的场景:
不要试图用jwt去代替session。这种模式下其实传统的session+cookie机制工作的更好,jwt因为其无状态和分布式,事实上只要在有效期内,是无法作废的,用户的签退更多是一个客户端的签退,服务端token仍然有效,你只要使用这个token,仍然可以登陆系统。另外一个问题是续签问题,使用token,无疑令续签变得十分麻烦,当然你也可以通过redis去记录token状态,并在用户访问后更新这个状态,但这就是硬生生把jwt的无状态搞成有状态了,而这些在传统的session+cookie机制中都是不需要去考虑的。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!