Oauth2协议那些事
1. 背景
首先,设想一种情境:你平常会使用一款照片存储App(以下照片服务指代),用来将自己喜欢的照片存放在上面以备随时查看。假如有一天,你想要打印其中的某张照片而且你找到了一款打印照片App(以下打印服务指代)。此时你应该怎么将照片给到打印App呢?其实这就涉及到了授权的问题,你必须让照片服务授权打印服务访问指定的照片。
也许,最直接的方式就是把用户和密码给到打印服务,这样的话打印服务就可以代替你直接去登录照片服务拿到任意的照片。但是这种方式很明显有极大的安全风险,因为你不能保证打印服务不会访问你的其他照片并且去做坏事。因此在这种背景下,OAuth2协议应运而生。本文就围绕Oauth2为主题,解析它的具体定义以及各种模式,更重要的是不同模式的使用场景。
2. Oauth2的相关概念
在具体讲解Oauth2的定义之前,有几个概念有必要先了解一下:
- 资源服务器(Resource Server): 存放受保护资源的服务器,
照片存储App在上面的情境中就可以看做是资源服务器 - 资源拥有者(Resource Owner):**:通常就是指对资源有拥有权的用户
- 客户端(Client): 想要访问受保护资源的对象,上面
打印照片App就是一种客户端(单页应用、无线应用等也属于客户端) - 授权服务器(Authorization Server):给客户端颁发授权凭证的服务器,通常是给客户端授权码、令牌等凭证
3. Oauth2的授权模式
本节具体讲解Oauth2四种不同的授权模式,分别是:授权码模式、隐含模式、密码模式、客户端凭证模式,以及它们不同的使用场景。
3.1 授权码模式(Authorization Code)
- 使用场景:
授权码模式是Oauth2协议里最安全的一种模式(微信、微博第三方登录都是基于该模式),如果上面照片服务和打印服务隶属于不同公司,并且打印服务有自己的服务器。那么在这种情景下,必须要用授权码模式保证资源的安全,它的主要流程是:

- 客户端需要先向授权服务器请求授权码
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攻击
- 客户端拿到授权码之后,去向授权服务器请求以获取到访问令牌
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:请求资源范围
- 拿到
token后,客户端就可以请求指定的api进行资源访问,请求格式如下:
curl -X GET http://localhost:8080/api/xxx -H 'Authorization:Bearer LIYcLu400YNX5CzJpZ39XG7J9kw'
授权码模式主要涉及到
code和token的获取,只有获取到token后才有权限访问资源。code是通过前端的方式传递的,但是就算code被截获,由于token是在服务器中完成请求的,一般clientSecret是不会泄露的,并且获取token还需state验证(state会和会话进行绑定),因此token泄露的风险极小,所以推荐使用这种模式来颁发token。
3.2 隐含模式(implicit)
- 使用场景:由于并不是所有的客户端都有服务器支持,假如
打印服务是个spa应用,那么授权码模式很显然并不适用,因此Oauth2还提供了隐含模式来处理这种情况。它的主要流程如下:

- 客户端向授权服务器直接请求获取
token,请求格式如下:
http://localhost:8080/oauth/authorize
?client_id=testClient&redirect_uri=http://localhost:8080/callback&response_type=token&scope=read_userInfo
- client_id:客户端凭证id,一般在授权服务器提前注册获取
- redirect_uri: 回调地址,用来将token回调给客户端
- response_type: 用来告诉授权服务器响应token
- scope: 需要申请访问的资源范围
需要注意的是这种模式并不是一种十分安全的模式,因为token有被泄漏的风险。因此除非是像上述这种必要的场景,一般不适用这种模式,并且在这种模式下token的失效时间需要尽可能的短。
- 拿到
token后请求资源服务器
curl -X GET http://localhost:8080/api/xxx -H 'Authorization:Bearer LIYcLu400YNX5CzJpZ39XG7J9kw'
3.3 密码模式(password)
- 使用场景:如果
照片服务和打印服务同属一个公司,那么可能不需要很严格的安全防范。因此Oauth2还提供了密码模式来颁发token`,主要流程如下:

- 客户端直接向授权服务器请求获取
token接口,请求格式如下:
curl -X POST --user testClient:testSecret http://localhost:8080/oauth/token
-H 'content-type:application/x-www-form-urlencoded'
-d 'grant_type=password&username=joe&password=123&scope=read_userInfo'
- testClient:testSecret:表名客户端身份,客户端id和客户端秘钥
- grant_type=password: 表名授权方式是密码模式
- username=joe&password=123:将密码和用户名传递给授权码服务器
- scope:请求资源范围
这种模式严格来说是很不安全的,因为你把用户名和密码给了客户端,然后代替你去登录网站。默认也不推荐使用这种模式,除非是特别信任的系统或者是同一组织的产品。
- 拿到
token后请求资源服务器
curl -X GET http://localhost:8080/api/user/info -H 'Authorization:Bearer LIYcLu400YNX5CzJpZ39XG7J9kw'
3.4 客户端凭证模式(Client Credentials)
- 使用场景:单纯机器和机器之间的交互,和用户并没有交互关系。那么客户端可能只需要向授权服务器注册好凭证保存下来就可以进行认证。针对这种情况,Oauth2通过
客户端凭证的方式来颁发token,主要流程如下:

- 获取
token
curl -X POST --user testClient:testSecret http://localhost:8080/oauth/token
-H 'content-type:application/x-www-form-urlencoded'
-d 'grant_type=client_credentials&scope=read_userInfo'
- testClient:testSecret:表名客户端凭证,客户端id和客户端秘钥
- grant_type=client_credentials: 表名授权方式是客户端凭证模式
- scope:请求资源范围
这种方式更加地简单,只需要向授权服务器申请过凭证,就可以访问资源,一般用于纯及机器之间的交互。
- 拿到
token后请求资源服务器
curl -X GET http://localhost:8080/api/user/info -H 'Authorization:Bearer LIYcLu400YNX5CzJpZ39XG7J9kw'
4. 总结
至此,关于oauth2协议的四种模式已经讲解完了,并且针对它们不同的使用场景也做了阐述。Oauth2协议在微服务系统盛行的今天有着很重要的作用,往往会在网关层担当权限控制的角色。并且Oauth2只是定义了协议,并不是具体的实现,像Spring Security Oauth2、Google OAuth Java Client等都对它有比较好的支持,具体的使用可以借助这些框架来展开。
5. 参考资料
- https://oauth.net/code/java/
- Oauth2 in action
- https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
Oauth2协议那些事的更多相关文章
- 一文带你了解 OAuth2 协议与 Spring Security OAuth2 集成!
OAuth 2.0 允许第三方应用程序访问受限的HTTP资源的授权协议,像平常大家使用Github.Google账号来登陆其他系统时使用的就是 OAuth 2.0 授权框架,下图就是使用Github账 ...
- Spring Security如何优雅的增加OAuth2协议授权模式
一.什么是OAuth2协议? OAuth 2.0 是一个关于授权的开放的网络协议,是目前最流行的授权机制. 数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据.系统从而产生一个短期的进入令 ...
- (转)TCP协议那些事
(上) TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的过程却能让人有很多收获.关于TCP这个协议的细节,我还是 ...
- Spring cloud微服务安全实战-4-4 OAuth2协议与微服务安全
Oauth2 解决了cookie和session的问题 搭建认证服务器 把依赖都复制进来 因为搭建的是Oauth的服务器,所以还需要导入oauth2 开始写代码 首先创建启动类 增加配置文件 端口设置 ...
- 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_03-用户认证技术方案-Oauth2协议
2.2 Oauth2认证 2.2.1 Oauth2认证流程 第三方认证技术方案最主要是解决认证协议的通用标准 问题,因为要实现 跨系统认证,各系统之间要遵循一定的 接口协议. OAUTH协议为用户资源 ...
- IP协议那些事
IP协议作为通信子网的最高层.提供无连接的数据报传输机制. IP协议的作用 寻址和路由 传递服务:提供不可靠,无连接的服务. 为什么说IP协议不可靠.无连接 不可靠:是指不能保证IP数据包能成成功到达 ...
- CAS集成oauth2协议的支持
参考https://blog.csdn.net/qq_34021712/article/details/82290876, 在springboot体系类,可以采用spring security oau ...
- TCP协议那些事
tcp三次握手 tcp四次挥手 tcp十种状态 tcp的2MSL问题 说明 2MSL即两倍的MSL,TCP的TIME_WAI ...
- SAML和OAuth2这两种SSO协议的区别
目录 简介 SAML SAML的缺点 OAuth2 OAuth2的缺点 两者的对比 CAS简介 简介 SSO是单点登录的简称,常用的SSO的协议有两种,分别是SAML和OAuth2.本文将会介绍两种协 ...
随机推荐
- 智能货柜 & 技术原理 (动态视觉识别 + 重力感应)
智能货柜 & 技术原理 (动态视觉识别 + 重力感应) 智能货柜 拥有智能化.精细化运营模式的智能货柜成为代替无人货架继前进的方式. 相比无人货架来说,智能货柜的技术门槛更高,拥有 RFID. ...
- front-end & web & best code editor
front-end & web & best code editor 2019 VS Code https://designrevision.com/best-code-editor/ ...
- React-Native Tutorials
React-Native Tutorials https://egghead.io/courses/react-native-fundamentals part free https://egghea ...
- vue-eahars生产编译报错
{ test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test'), resolve('node_mo ...
- 读懂框架设计的灵魂—Java反射机制
尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 CS-Wiki(Gitee 官 ...
- Django框架admin后台管理和用户端静态文件
目录 一.admin后台管理 1. 如何使用 2. 路由分发的本质 二.用户上传的静态文件的展示 1. media配置 2. 手动开设media接口 三.图片防盗链 一.admin后台管理 djang ...
- 分布式实时处理系统——C++高性能编程
[前言]基于通信基础,介绍Hurricane实时处理系统的工程实现,主要使用C++语言. 一.IPC.socket.异步I/O epoll 二.C++11 1.linux内存管理中使用RALL原则,C ...
- STL容器整理
1.vector c++STL中的可变长度数组,主要支持操作有:建立,添加到末尾,返回长度,调整大小,定义迭代器及对迭代器的具体操作.具体如下: 1.建立一个元素类型为int的可变长度数组v,最开始N ...
- 《C++ Primer》笔记 第1章 开始
输出运算符<< 的计算结果就是其左侧运算对象 std::endl 结束当前行,并将与设备关联的缓冲区中的内容刷到设备中. 程序员常常在调试时添加打印语句.这类语句应该保证"一直& ...
- redis基础:redis下载安装与配置,redis数据类型使用,redis常用指令,jedis使用,RDB和AOF持久化
知识点梳理 课堂讲义 课程计划 1. REDIS 入 门 (了解) (操作) 2. 数据类型 (重点) (操作) (理解) 3. 常用指令 (操作) 4. Jedis (重点) (操作) ...