OAuth2.0授权登录
最近工作中遇到了多系统间的授权登录,对OAuth2.0进行了学习研究,并总结备忘。
【场景】

我们登录一些论坛等网站的时候,如果不想单独注册该网站账号,可以选择用微信或QQ账号进行授权登录。 这样的第三方登录方式到底是怎么实现的呢?难道是腾讯把我们微信或QQ账号信息卖给了这些网站?很显然,腾讯是不会这么干的,这种登录方式的实现,其实就是使用的OAuth2.0的授权登录方式。
类似地,在公司内部,如果公司有多套不同的软件系统,例如公司内网的财务报销系统、考勤系统、报销系统、人事系统等,也可以实现一个员工账号就能授权访问所有系统,而不需要每个系统都开通单独的账号,设置独立的密码。这是通常所说的SSO单点登录,而OAuth2.0是单点登录的实现方式之一。
【定义】
OAuth2.0是一种允许第三方应用程序使用资源所有者的凭据获得对资源有限访问权限的一种授权协议。
例如在上述例子中,通过微信登录论坛的过程,就相当于微信允许该论坛作为第三方应用程序在经过微信用户授权后,通过微信颁发的授权凭证有限地访问用户的微信头像、手机号,性别等受限制的资源,从而来构建自身的登录逻辑。
注:在OAuth2.0协议中,第三方应用程序获取的凭证并不等同于资源拥有者持有的用户名和密码,以上面例子来说,微信是不会直接将用户的用户名、密码等信息作为凭证返回给该论坛的。这种授权访问凭证一般来说就是一个表示特定范围、生存周期和其访问权限的一个由字符串组成的访问令牌,也就是我们常说的token。在这种模式下OAuth2.0协议中通过引入一个授权层来将第三方应用程序与资源拥有者进行分离,而这个授权层也就是常说的“auth认证服务/sso单点登录服务器”。
在OAuth2.0协议中定义了以下四个角色:
1)resource owner(资源拥有者)
即能够有权授予对保护资源访问权限的实体。例如我们使用通过微信账号登录论坛,而微信账号信息的实际拥有者就是微信用户,也被称为最终用户。
2)resource server(资源服务器)
承载受保护资源的服务器,能够接收使用访问令牌对受保护资源的请求并响应,它与授权服务器可以是同一服务器(下述的“简化模式”),也可以是不同服务器(下述的“授权码模式”)。在上述例子中该角色就是微信服务器。
3)client(客户端)
代表资源所有者及其授权发出对受保护资源请求的应用程序。在上面的例子中的用户要注册的论坛就是该角色。
4)authorization server(授权服务器)
认证服务器,即服务提供商专门用来处理认证授权的服务器。例如微信开放平台提供的认证服务的服务器。
【流程】
还是以微信授权登录举例,流程如下:

流程说明:
- 首先微信用户点击豆瓣网论坛的微信授权登录按钮后,豆瓣网论坛会将请求通过URL重定向的方式跳转至微信用户授权界面;
- 此时微信用户实际上是在微信上进行身份认证,与豆瓣网论坛并无交互了,这一点非常类似于购物后,使用网银支付的场景;
- 用户使用微信客户端扫描二维码认证或者输入用户名密码后,微信会验证用户身份信息的正确性,如正确,则认为用户确认授权微信登录豆瓣网论坛,此时会先生成一个临时凭证,并携带此凭证通过用户浏览器将请求重定向回豆瓣网在第一次重定向时携带的callBackUrl地址;
- 之后用户浏览器会携带临时凭证访问豆瓣网服务,豆瓣网则通过此临时凭证再次调用微信授权接口,获取正式的访问凭据access_token;
- 在豆瓣网获取到微信授权访问凭据access_token后,此时用户的授权基本上就完成了,后续豆瓣网要做的只是通过此token再访问微信提供的相关接口,获取微信允许授权开发的用户信息,如头像,昵称等,并据此完成自身的用户逻辑及用户登录会话逻辑。
【模式】
在上述流程中比较关键的动作是resource owner(资源拥有者,用户)怎么样才能给Client(豆瓣网论坛)授权,因为只有有了这个授权,Client角色才可以获取访问令牌(access_token),进而通过令牌访问其他资源接口。而关于客户端如何获得授权的问题,在OAuth2.0中定义了四种授权方式,目前微信授权登录,使用的就是其中最常用的一种:“授权码模式”(authorization_code)。
OAuth2.0定义了四种授权模式,它们分别是:
- 授权码模式(authorization code)
- 简化模式(implicit)
- 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
四种模式对比说明:
1.授权码模式(authorization code)
功能最完整、流程最严密的授权模式,安全性最高,也最为常用。
特点是通过客户端的后台服务器,与“服务提供商”的认证服务进行互动(如微信开放平台),如上述微信账号登录豆瓣网的流程就是授权码模式的实现。
这种模式下授权代码并不是客户端直接从资源所有者获取,而是通过授权服务器(authorization server)作为中介来获取,授权认证的过程也是资源所有者直接通过授权服务器进行身份认证,避免了资源所有者身份凭证与客户端共享的可能,因此是十分安全的。
2.简化模式(implicit grant type)
简化模式是对授权码模式的简化,用于在浏览器中使用脚本语言如JS实现的客户端中,特点是不通过客户端应用程序的服务器,而是直接在浏览器中向认证服务器申请令牌,跳过了“授权码临时凭证”这个步骤。其所有的步骤都在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。如果使用此种授权方式来实现微信登录豆瓣网论坛的过程流程示例如下:

可以看出,与授权码模式的不同之处在于:在第4步用户完成授权后,认证服务器是直接返回了access_token令牌至用户浏览器端,而并没有先返回临时授权码code,然后由客户端的后端服务去通过授权码再去获取access_token令牌,从而省去了一个跳转步骤,提高了交互效率。
但是由于这种方式访问令牌access_token会在URL片段中进行传输,因此可能会导致访问令牌被其他未经授权的第三方截取,所以安全性上并不是那么的强壮。
3.密码模式(resource owner password credentials)
在密码模式中,用户需要向客户端提供自己的用户名和密码,客户端使用这些信息向“服务提供商”索要授权。这相当于在豆瓣网中使用微信登录,我们需要在豆瓣网输入微信的用户名和密码,然后由豆瓣网使用我们的微信用户名和密码去向微信服务器获取授权信息。
这种模式一般用在用户对客户端高度信任的情况下,因为虽然协议规定客户端不得存储用户密码,但是实际上这一点并不是特别好强制约束。就像在豆瓣网输入了微信的用户名和密码,豆瓣网存储不存储我们并不是很清楚,所以安全性是非常低的。因此一般情况下是不会考虑使用这种模式进行授权的。公司内网之间相互信任的子系统间也许才有可能使用。
如果使用此种授权方式来实现微信登录豆瓣网论坛的过程流程示例如下:

4.客户端模式(client credentials)
客户端模式是指客户端以自己的名义,而不是以用户的名义,向“服务提供方”进行认证。严格地说,客户端模式并不属于OAuth2.0协议所要解决的问题。在这种模式下,用户并不需要对客户端授权,用户直接向客户端注册,客户端以自己的名义要求“服务提供商”提供服务,其实不存在授权问题。

步骤如下:
(1)客户端向认证服务器进行身份认证,并要求一个access_token令牌。
(2)认证服务器确认无误后,向客户端提供访问access_token令牌。
(3)客户端后续携带access_token令牌继续后续业务请求流程。
步骤(1)中,客户端发出的HTTP请求,包含以下参数:
- grant_type:表示授权类型,此处的值固定为"client_credentials",必选项。
- scope:表示权限范围,可选项。
示例:
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded grant_type=client_credentials
认证服务器必须以某种方式,验证客户端身份。然后在步骤(2)中,认证服务器向客户端提供访问access_token令牌,下面是一个例子。
示例:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache {
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"iss":"签发授权者",
"sub":"服务使用者",
"aud":"服务提供者",
"exp":"过期时间",
"iat":"签发时间",
"other_custom_parameter":"value"
}
综上所述,虽然在OAuth2.0协议中定义了四种客户端授权认证模式,但是实际上大部分实际应用场景中使用的都是授权码(authorization code)的模式,如微信开放平台、微博开放平台等使用的基本都是授权码认证模式。
【更新令牌】
如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌"申请一个新的访问令牌。
客户端发出更新令牌的HTTP请求,包含以下参数:
- grant_type:表示使用的授权模式,此处的值固定为"refresh_token",必选项。
- refresh_token:表示早前收到的更新令牌,必选项。
- scope:表示申请的授权范围,不可以超出上一次申请的范围,如果省略该参数,则表示与上一次一致。
示例:
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
OAuth2.0授权登录的更多相关文章
- 【第二十一篇】手C# MVC 微信授权登录 OAuth2.0授权登录
首先一定要熟读,最起码过一遍微信开发者文档 微信开发者文档 文档写的很清楚 授权登录四步走 在正文开始前,我得讲清楚一个事情 敲黑板,划重点:微信一共有两个 access_token 一个是7200就 ...
- Java微信公众平台开发(十六)--微信网页授权(OAuth2.0授权)获取用户基本信息
转自:http://www.cuiyongzhi.com/post/78.html 好长时间没有写文章了,主要是最近的工作和生活上的事情比较多而且繁琐,其实到现在我依然还是感觉有些迷茫,最后还是决定静 ...
- Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端
Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端 目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Se ...
- 使用DotNetOpenAuth搭建OAuth2.0授权框架
标题还是一如既往的难取. 我认为对于一个普遍问题,必有对应的一个简洁优美的解决方案.当然这也许只是我的一厢情愿,因为根据宇宙法则,所有事物总归趋于混沌,而OAuth协议就是混沌中的产物,不管是1.0. ...
- 新浪微博Oauth2.0授权认证及SDK、API的使用(Android)
---------------------------------------------------------------------------------------------- [版权申明 ...
- 使用微服务架构思想,设计部署OAuth2.0授权认证框架
1,授权认证与微服务架构 1.1,由不同团队合作引发的授权认证问题 去年的时候,公司开发一款新产品,但人手不够,将B/S系统的Web开发外包,外包团队使用Vue.js框架,调用我们的WebAPI,但是 ...
- OAuth2.0 授权码理解
OAuth2.0授权模式 本篇文章介绍OAuth的经典授权模式,授权码模式 所谓授权无非就是授权与被授权,被授权方通过请求得到授权方的同意,并赋予某用权力,这个过程就是授权. 那作为授权码 ...
- 工作笔记—新浪微博Oauth2.0授权 获取Access Token (java)
java发送新浪微博,一下博客从注册到发布第一条微博很详细 利用java语言在eclipse下实现在新浪微博开发平台发微博:http://blog.csdn.net/michellehsiao/art ...
- 深入浅出OAuth2.0授权
一.前言 说到OAuth,先来一段百度到的比较官方的解释: OAUTH协议为用户资源的授权提供了一个安全的.开放而又简易的标准.与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信 ...
随机推荐
- python学习-for
# 对字典的遍历. key-value# dict_my = {"class":"python17","goal":"翻倍&quo ...
- 区块链学习——HyperLedger-Fabric v1.0环境搭建详细教程
相对与v0.6版本来说,1.0版本改变较大,此处不多说,只是将小白自己搭建1.0环境的过程分享给大家.希望对大家能有所帮助! 这一篇可能对前面的环境搭建会写的有些粗略,如有疑问,可阅读上一篇V0.6版 ...
- 《Java练习题》习题集三
编程合集: https://www.cnblogs.com/jssj/p/12002760.html Java总结:https://www.cnblogs.com/jssj/p/11146205.ht ...
- 【Dos】复制指定文件夹下所有文件到另外指定文件夹下
bat代码如下: @echo off @set /p fromFile=from: @set /p toFile=to: rem 找到所有文件 dir /b /s %fromFile%\ *.gz & ...
- Hive concat函数连接后结果为null
Hive concat函数连接后结果为null concat函数是用来连接字符串的 使用示例: select concat('Hello','World','Java'); 运行结果: 最近我们在做需 ...
- java基础|自定义java线程池
线程池创建的参数 在创建线程的各种方式中我们有讲到过通过创建线程池来完成异步操作,但实际上jdk提供的Executors来创建线程池都还有些缺陷,线程池有以下几个参数: 代码节选自源码ThreadPo ...
- IT兄弟连 HTML5教程 CSS3属性特效 渐变2 线性渐变实例
3 线性渐变实例 一.颜色从顶部向底部渐变 制作从顶部到底部直线渐变有三种方法,第一种是起点参数不设置,因为起点参数的默认值为“top”:第二种方法起点参数设置为“top”:第三种起点参数使用“-90 ...
- 互联网大厂Java面试题集—Spring boot面试题(一)
Spring Boot 需要独立的容器运行吗? 可以不需要,内置了 Tomcat/ Jetty 等容器.通过pom.xml中导入依赖: <!--spring-boot-starter-web:代 ...
- C# 使用.net core 驱动树莓派的IO信号
如何使用.net core来驱动树莓派的IO信号?是我们的实际项目需求中,可能就会有这种小项目,我们要输出一个IO信号,此处我们拿了树莓派4做测试 一共有两排引脚,引脚的顺序定义及功能如下: 我们就参 ...
- 分布式图数据库 Nebula Graph 中的集群快照实践
1 概述 1.1 需求背景 图数据库 Nebula Graph 在生产环境中将拥有庞大的数据量和高频率的业务处理,在实际的运行中将不可避免的发生人为的.硬件或业务处理错误的问题,某些严重错误将导致集群 ...