深入理解OAuth 2.0

x33g5p2x  于2022-03-02 转载在 其他  
字(4.6k)|赞(0)|评价(0)|浏览(304)

介绍

2012年10月,OAuth 2.0协议正式发布为RFC 6749。现在百度开放平台,腾讯开放平台等大部分的开放平台都是使用的OAuth 2.0协议作为支撑。

OAuth是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容。

在OAuth 2.0的认证和授权的过程中主要包括以下角色定义:

Resource owner: 资源所有者(通常指用户或者提供资源服务的平台)
Resource server:资源服务器(托管受保护资源的服务器)
Client:客户端(浏览器、APP)
Authorization server:授权服务器(颁发访问令牌、验证令牌、刷新令牌)

交互过程
OAuth 在 “客户端” 与 “服务提供商” 之间,设置了一个授权层(authorization layer)。“客户端” 不能直接登录 “服务提供商”,只能登录授权层,以此将用户与客户端区分开来。“客户端” 登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。“客户端” 登录授权层以后,“服务提供商” 根据令牌的权限范围和有效期,向 “客户端” 开放用户储存的资料。

腾讯会议,采用的是授权码模式,

  1. 通过微信扫一扫,拿到本人的授权码
  2. 然后腾讯会议通过授权码就可以获取,用户指定范围内的微信里的信息
  3. 然后登录成功

手机扫一扫后,会显示腾讯会议需要申请的授权信息

四种授权方式

  • 密码模式(resource owner password credentials)
  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 客户端模式(client credentials)

密码模式(resource owner password credentials)

这种模式是最不推荐的,因为 client 可能存了用户密码
这种模式主要用来做遗留项目升级为 oauth2 的适配方案
当然如果 client 是自家的应用(比如某公司网站下面有好多个子系统这些子系统都是自己公司的),也是可以
支持 refresh token
授权码模式(authorization code)

这种模式算是正宗的 oauth2 的授权模式
设计了 auth code,通过这个 code 再获取 token
支持 refresh token(判断token过期刷新token)
简化模式(implicit)
这种模式比授权码模式少了 code 环节,回调 url 直接携带 token
这种模式的使用场景是基于浏览器的应用
这种模式基于安全性考虑,建议把 token 时效设置短一些
不支持 refresh token(过期后从新拿新的token)
客户端模式(client credentials)

这种模式直接根据 client 的 id 和密钥即可获取 token,无需用户参与
这种模式比较合适消费 api 的后端服务,比如拉取一组用户信息等
不支持 refresh token,主要是没有必要,refresh token 的初衷主要是为了用户体验不想用户重复输入账号密码来换取新 token,因而设计了 refresh token 用于换取新 token,这种模式由于没有用户参与,而且也不需要用户账号密码,仅仅根据自己的 id 和密钥就可以换取新 token,因而没必要 refresh token

应用场景

授权码模式(Authorization Code)

使用场景:授权码模式是Oauth2协议里最安全的一种模式(微信、微博第三方登录都是基于该模式),如果上面照片服务和打印服务隶属于不同公司,并且打印服务有自己的服务器。那么在这种情景下,必须要用授权码模式保证资源的安全.

它的主要流程是:

1、客户端需要先向授权服务器请求授权码code,请求的格式如下

http://localhost:8080/oauth/authorize?client_id=testClient&redirect_uri=http://localhost:8080/callback&response_type=code&scope=read_userInfo&state=x1f2xs
  • client_id:客户端凭证id,一般在授权服务器提前注册获取
  • redirect_uri:回调地址,用来回调授权码给客户端服务器
  • response_type:用来告诉授权服务器响应授权码
  • scope:需要申请访问的资源范围
  • state:随机数,用来防止csrf攻击

2、客户端拿到授权码之后,去向授权服务器请求以获取到访问令牌token,请求格式如下:

curl -X POST --user testClient:testSecret http://localhost:8080/oauth/token 
-H 'content-type:application/x-www-form-urlencoded' 
-d "code=QvjUaf&grant_type=authorization_code&redirect_uri=http://localhost:8080/callback&scope=read_userInfo"
  • testClient:testSecret:表名客户端身份,客户端id和客户端秘钥
  • code:授权服务器返回的授权码
  • grant_type=authorization_code:表名授权方式是授权码模式
  • redirect_uri:回调地址,一般后端服务器会去访问资源然后定位到首页或者用户页
  • scope:请求资源范围

3、拿到token后,携带token放入请求体中,客户端就可以请求指定的api进行资源访问,请求格式如下:

curl  -H 'Authorization:Bearer LIYcLu400YNX5CzJpZ39XG7J9kw'  -X GET         http://localhost:8080/api/xxx

授权码模式主要涉及到code和token的获取,只有获取到token后才有权限访问资源。code是通过前端的方式传递的,但是就算code被截获,由于token是在服务器中完成请求的,一般ClientSecret是不会泄露的,并且获取token还需state验证(state会和会话进行绑定),因此token泄露的风险极小,所以推荐使用这种模式来颁发token。

隐含模式(implicit)

使用场景:由于并不是所有的客户端都有服务器支持,假如打印服务是个spa应用(就是只有一张Web页面的应用),那么授权码模式很显然并不适用,因此Oauth2还提供了隐含模式来处理这种情况。当然很多web程序的单点登录流程也是使用的这种模式然后进行扩展

它的主要流程如下:

1、客户端向授权服务器直接请求获取token,请求格式如下:

http://localhost:8080/oauth/authorize?client_id=testClient&redirect_uri=http://localhost:8080/callback&response_type=token&scope=read_userInfo
  1. client_id:客户端凭证id,一般在授权服务器提前注册获取
  2. redirect_uri:回调地址,用来将token回调给客户端
  3. response_type:用来告诉授权服务器响应token
  4. scope:需要申请访问的资源范围
    需要注意的是这种模式并不是一种十分安全的模式,因为token有被泄漏的风险。因此除非是像上述这种必要的场景,一般不适用这种模式,并且在这种模式下token的失效时间需要尽可能的短。

2、拿到token后请求资源服务器

curl  -H 'Authorization:Bearer LIYcLu400YNX5CzJpZ39XG7J9kw'  -X GET         http://localhost:8080/api/xxx

密码模式(password)

使用场景:如果照片服务和打印服务同属一个公司,那么可能不需要很严格的安全防范。因此Oauth2还提供了密码模式来颁发token`,主要流程如下:

1、客户端向授权服务器直接请求获取token,请求格式如下:

curl  -X POST  http://localhost:8080/oauth/token 
-H 'content-type:application/x-www-form-urlencoded' 
-d '{ "client_id":"abcnsd1xxc","password":123,"username":"joe","scope": "read_userInfo"}'
  • client_id:axca1:表名客户端身份
  • username=joe&password=123:将密码和用户名传递给授权码服务器
  • scope:请求资源范围
    需要注意的是这种模式并不是一种十分安全的模式,因为token有被泄漏的风险。因此除非是像上述这种必要的场景,一般不适用这种模式,并且在这种模式下token的失效时间需要尽可能的短。

2、拿到token后请求资源服务器

curl  -H 'Authorization:Bearer LIYcLu400YNX5CzJpZ39XG7J9kw'  -X GET http://localhost:8080/api/user/info

客户端凭证模式(Client Credentials)

使用场景:单纯机器和机器之间的交互,和用户并没有交互关系。那么客户端可能只需要向授权服务器注册好凭证保存下来就可以进行认证,简单来说就是密码模式的基础上去掉了密码。针对这种情况,Oauth2通过客户端凭证的方式来颁发token,主要流程如下:

curl -X POST  http://localhost:8080/oauth/token 
-H 'content-type:application/x-www-form-urlencoded' 
-d '{ "client_id":"abcnsd1xxc","scope": "read_userInfo"}'
  • client_id:axca1:表名客户端身份(注册的凭证)
  • scope: 请求资源范围

2、拿到token后请求资源服务器

curl -H 'Authorization:Bearer LIYcLu400YNX5CzJpZ39XG7J9kw'  -X GET http://localhost:8080/api/user/info

更新令牌(refresh_token)

如果令牌到期了那么有两种更新令牌的方式:

  1. 拿老的换新的
  2. 刷新令牌过期时间

如果安全性比较高的话,可以使用拿老的换新的,否则就使用刷新令牌过期时间,具体细节可以根据场景进行定制化开放
点赞 -收藏-关注-便于以后复习和收到最新内容有其他问题在评论区讨论-或者私信我-收到会在第一时间回复如有侵权,请私信联系我感谢,配合,希望我的努力对你有帮助^_^

相关文章