首页 >> 手游攻略

移花接木 4.1

大家好,今天小编来为大家解答移花接木 4.1这个问题,OAuth 2.0 授权认证详解很多人还不知道,现在让我们一起来看看吧!

OAuth2.0授权认证详解

一、认识OAuth2.0

1.1OAuth2.0应用场景

OAuth2.0标准目前被广泛应用在第三方登录场景中,以下是虚拟出来的角色,阐述OAuth2能帮我们干什么,引用阮一峰这篇理解OAuth2.0中的例子:

有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让"云冲印"读取自己储存在Google上的照片。

问题是只有得到用户的授权,Google才会同意"云冲印"读取这些照片。那么,"云冲印"怎样获得用户的授权呢?

传统方法是,用户将自己的Google用户名和密码,告诉"云冲印",后者就可以读取用户的照片了。这样的做法有以下几个严重的缺点。

(1)"云冲印"为了后续的服务,会保存用户的密码,这样很不安全。(2)Google不得不部署密码登录,而我们知道,单纯的密码登录并不安全。(3)"云冲印"拥有了获取用户储存在Google所有资料的权力,用户没法限制"云冲印"获得授权的范围和有效期。(4)用户只有修改密码,才能收回赋予"云冲印"的权力。但是这样做,会使得其他所有获得用户授权的第三方应用程序全部失效。(5)只要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。

1.2名词概念

OAuth就是为了解决上面这些问题而诞生的。在详解OAuth之前,需要明确一些基本的概念,从上面场景中抽象出以下概念。

第三方应用程序

Third-partyapplication:第三方应用程序,本文中又称"客户端"(client),即上一节例子中的"云冲印"。

HTTP服务提供商

HTTPservice:HTTP服务提供商,本文中简称"服务提供商",即上一节例子中的Google。

资源所有者

ResourceOwner:资源所有者,本文中又称"用户"(user)。

用户代理

UserAgent:用户代理,本文中就是指浏览器。

认证服务器

Authorizationserver:认证服务器,即服务提供商专门用来处理认证的服务器。

资源服务器

Resourceserver:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。

知道了上面这些名词,就不难理解,OAuth的作用就是让"客户端"安全可控地获取"用户"的授权,从而可以和"服务商提供商"进行互动。

二、OAuth的授权认证流程

2.1认证思路

OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorizationlayer)。"客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。

"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。

2.2认证流程

官方RFC6749文件中的OAuth2.0流程图有点晦涩,优化了一下:

用户访问第三方应用程序(简称:客户端)以后,客户端要求用户给予授权。用户同意给予客户端授权。客户端使用第2步获得的授权,向认证服务器申请令牌。认证服务器对客户端进行认证以后,确认无误,同意发放令牌。客户端使用令牌,向资源服务器申请获取资源。资源服务器确认令牌无误,同意向客户端开放资源。

上述中的第2步是关键,即用户怎样才能给于客户端授权。有了这个授权以后,客户端就可以获取令牌,进而凭令牌获取资源。

三、四种授权模式

上一小节可以得出用户对客户端的授权动作是核心,客户端必须得到用户的授权(authorizationgrant),才能获得令牌(accesstoken)。OAuth2.0定义了四种授权方式:

3.1授权码模式(authorizationcode)

授权码(authorizationcode)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。

3.2简化模式(implicit)

有些Web应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC6749就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。

3.3密码模式(resourceownerpasswordcredentials)

如果你高度信任某个应用,RFC6749也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。

3.4客户端模式(clientcredentials)

最后一种方式是凭证式(clientcredentials),适用于没有前端的命令行应用,即在命令行下请求令牌。

四、授权码模式详解

4.1授权码模式流程

授权码模式(authorizationcode)是功能最完整、流程最严密安全的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。

注意这种方式适用于那些有后端的Web应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。

授权码模式流程如下:

用户访问客户端,客户端将用户导向认证服务器。用户选择是否给予客户端授权。假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirectionURI),同时附上一个授权码。客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台服务器上完成的,对用户不可见。认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(accesstoken)和更新令牌(refreshtoken)。

从上述的流程描述可知,只有第2步需要用户进行授权操作,之后的流程都是在客户端的后台和认证服务器后台之前进行"静默"操作,对于用户来说是无感知的。

下面是上面这些步骤所需要的参数。

4.2授权码模式流程的五个步骤

第1步骤

参数说明

第1步骤中,客户端申请认证的URI,包含以下参数:

response_type:表示授权类型,必选项,此处的值固定为"code"client_id:表示客户端的ID,必选项redirect_uri:表示重定向URI,可选项scope:表示申请的权限范围,可选项state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

示例

A网站提供一个链接,用户点击后就会跳转到B网站,授权用户数据给A网站使用。下面就是A网站跳转B网站的一个示意链接:

https://b.com/oauth/authorize?nresponse_type=code&nclient_id=CLIENT_ID&nredirect_uri=CALLBACK_URL&nscope=readn复制代码n

上面URL中:

response_type参数表示要求返回授权码(code);

client_id参数让B网站知道是谁在请求;

redirect_uri参数是B网站接受或拒绝请求后的跳转网址;

scope参数表示要求的授权范围(这里是只读)。

第2步骤

第2步骤中,用户跳转后,B网站会要求用户登录,然后询问是否同意给予A网站授权。

第3步骤

参数说明

第3步骤中,服务器回应客户端的URI,包含以下参数:

code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

示例

在第2步骤用户表示同意之后,这时B网站就会跳回redirect_uri参数指定的网址。跳转时,会传回一个授权码,就像下面这样。

https://a.com/callback?code=AUTHORIZATION_CODEn复制代码n

上面URL中,code参数就是授权码。

第4步骤

参数说明

第4步骤中,客户端向认证服务器申请令牌的HTTP请求,包含以下参数:

grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。code:表示上一步获得的授权码,必选项。redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。client_id:表示客户端ID,必选项

示例

在第3步骤中,A网站拿到授权码以后,就可以在后端,向B网站请求令牌。

https://b.com/oauth/token?nclient_id=CLIENT_ID&nclient_secret=CLIENT_SECRET&ngrant_type=authorization_code&ncode=AUTHORIZATION_CODE&nredirect_uri=CALLBACK_URLn复制代码n

上面URL中:

client_id参数和client_secret参数用来让B确认A的身份(client_secret参数是保密的,因此只能在后端发请求);

grant_type参数的值是AUTHORIZATION_CODE,表示采用的授权方式是授权码;

code参数是上一步拿到的授权码;

redirect_uri参数是令牌颁发后的回调网址。

第5步骤

参数说明

第5步骤中,认证服务器发送的HTTP回复,包含以下参数:

access_token:表示访问令牌,必选项。token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。

示例

第4步骤中,B网站收到请求以后,就会颁发令牌。具体做法是向redirect_uri指定的网址,发送一段JSON数据:

HTTP/1.1200OKnContent-Type:application/json;charset=UTF-8nCache-Control:no-storenPragma:no-cachen{n"access_token":"ACCESS_TOKEN",n"token_type":"bearer",n"expires_in":2592000,n"refresh_token":"REFRESH_TOKEN",n"scope":"read",n"uid":100101,n"info":{...}n}n复制代码n

上面JSON数据中,access_token字段就是令牌,A网站在后端拿到了。注意:HTTP头信息中明确指定不得缓存。

五、令牌(Token)传递方式

当客户端(第三方应用程序)拿到访问资源服务器的令牌时,便可以使用这个令牌进行资源访问了。

在第三方应用程序拿到access_token后,如何发送给资源服务器这个问题并没有在RFC6729文件中定义,而是作为一个单独的RFC6750文件中独立定义了。这里做以下简单的介绍,主要有三种方式如下:

URIQueryParameterAuthorizationRequestHeaderFieldForm-EncodedBodyParameter

5.1请求头参数传递

AuthorizationRequestHeaderField,因为在HTTP应用层协议中,专门有定义一个授权使用的RequestHeader,所以也可以使用这种方式:

GET/resourceHTTP/1.1nHost:server.example.comnAuthorization:BearermF_9.B5f-4.1JqMn复制代码n

其中"Bearer"是固定的在access_token前面的头部信息。

5.2表单编码传递

使用RequestBody这种方式,有一个额外的要求,就是RequestHeader的Content-Type必须是固定的application/x-www-form-urlencoded,此外还有一个限制就是不可以使用GET访问,这个好理解,毕竟GET请求是不能携带RequestBody的。

POST/resourceHTTP/1.1nHost:server.example.comnContent-Type:application/x-www-form-urlencodednaccess_token=mF_9.B5f-4.1JqMn复制代码n

5.3URI请求参数传递

URIQueryParameter,这种使用途径应该是最常见的一种方式,非常简单,比如:

GET/resource?access_token=mF_9.B5f-4.1JqMHTTP/1.1nHost:server.example.comn复制代码n

在我们请求受保护的资源的Url后面追加一个access_token的参数即可。另外还有一点要求,就是Client需要设置以下RequestHeader的Cache-Control:no-store,用来阻止access_token不会被Web中间件给log下来,属于安全防护方面的一个考虑。

5.4令牌的刷新

为了防止客户端使用一个令牌无限次数使用,令牌一般会有过期时间限制,当快要到期时,需要重新获取令牌,如果再重新走授权码的授权流程,对用户体验非常不好,于是OAuth2.0允许用户自动更新令牌。

具体方法是,B网站颁发令牌的时候,一次性颁发两个令牌,一个用于获取数据,另一个用于获取新的令牌(refreshtoken字段)。令牌到期前,用户使用refreshtoken发一个请求,去更新令牌。

https://b.com/oauth/token?ngrant_type=refresh_token&nclient_id=CLIENT_ID&nclient_secret=CLIENT_SECRET&nrefresh_token=REFRESH_TOKENn复制代码n

上面URL中:

grant_type参数为refresh_token表示要求更新令牌,此处的值固定为refresh_token,必选项;

client_id参数和client_secret参数用于确认身份;

refresh_token参数就是用于更新令牌的令牌。

B网站验证通过以后,就会颁发新的令牌。

注意:第三方应用服务器拿到刷新令牌必须存于服务器,通过后台进行重新获取新的令牌,以保障刷新令牌的保密性。

六、OAuth2的安全问题

6.1CSRF攻击

应用程序在早期使用OAuth2的时候爆发过不少相关的安全方面的漏洞,其实仔细分析后会发现大都都是没有严格遵循OAuth2的安全相关的指导造成的,相关的漏洞事件自行搜索。

其实OAuth2在设计之初是已经做了很多安全方面的考虑,并且在RFC6749中加入了一些安全方面的规范指导。比如:

要求Authorizationserver进行有效的客户端验证;client_serect,access_token,refresh_token,code等敏感信息的安全存储(不得泄露给第三方)、传输通道的安全性(TSL的要求);维持refresh_token和第三方应用的绑定,刷新失效机制;维持AuthorizationCode和第三方应用的绑定,这也是state参数为什么是推荐的一点,以防止CSRF攻击;保证上述各种令牌信息的不可猜测行,以防止被猜测得到;

安全无小事,这方面是要靠各方面(开放平台,第三方开发者)共同防范的。

6.2攻击流程

假设有用户张三,攻击者李四,第三方"云冲印"应用(它集成了第三方社交账号登录,并且允许用户将社交账号和"云冲印"中的账号进行绑定),以及OAuth2服务提供者Google。

步骤1

攻击者李四登录"云冲印"网站,并且选择绑定自己的Google账号

步骤2

"云冲印"网站将李四重定向到Google,由于他之前已经登录过Google,所以Google直接向他显示是否授权"云冲印"访问的页面。

步骤3

李四在点击"同意授权"之后,截获Google服务器返回的含有Authorizationcode参数的HTTP响应。

步骤4

李四精心构造一个Web页面,它会触发"云冲印"网站向Google发起令牌申请的请求,而这个请求中的AuthorizationCode参数正是上一步截获到的code。

步骤5

李四将这个Web页面放到互联网上,等待或者诱骗受害者张三来访问。

步骤6

张三之前登录了"云冲印"网站,只是没有把自己的账号和其他社交账号绑定起来。在张三访问了李四准备的这个Web页面,令牌申请流程在张三的浏览器里被顺利触发,"云冲印"网站从Google那里获取到access_token,但是这个token以及通过它进一步获取到的用户信息却都是攻击者李四的。

步骤7

"云冲印"网站将李四的Google账号同张三的"云冲印"账号关联绑定起来,从此以后,李四就可以用自己的Google账号通过OAuth登录到张三在"云冲印"网站中的账号,堂而皇之的冒充张三的身份执行各种操作。

从整体上来看,本次CSRF攻击的时序图应该是下面这个样子的:

从上图中可以看出,造成CSRF攻击漏洞问题的关键点在于,OAuth2的认证流程是分为好几步来完成的,在上一章节授权码模式流程中的流程图中的第4步骤中,第三方应用在收到一个GET请求时,除了能知道当前用户的cookie,以及URL中的AuthorizationCode之外,难以分辨出这个请求到底是用户本人的意愿,还是攻击者利用用户的身份伪造出来的请求。

于是,攻击者就能使用移花接木的手段,提前准备一个含有自己的AuthorizationCode的请求,并让受害者的浏览器来接着完成后续的令牌申请流程。

6.3解决方案

要防止这样的攻击其实很容易,作为第三方应用的开发者,只需在OAuth认证过程中加入state参数,并验证它的参数值即可。具体细节如下:

在将用户重定向到资源认证服务器授权界面的时候,为当前用户生成一个随机的字符串,并作为state参数加入到URL中,同时存储一份到session中。当第三方应用收到资源服务提供者返回的AuthorizationCode请求的时候,验证接收到的state参数值。如果是正确合法的请求,那么此时接收到的参数值应该和上一步提到的为该用户生成的state参数值(存于当前用户的session中)完全一致,否则就是异常请求。state参数值需要具备下面几个特性:不可预测性:足够的随机,使得攻击者难以猜到正确的参数值关联性:state参数值和当前用户会话(usersession)是相互关联的唯一性:每个用户,甚至每次请求生成的state参数值都是唯一的时效性:state参数一旦被使用则立即失效

state参数在OAuth2认证过程中不是必选参数,因此在早期第三方应用开发者在集成OAuth2认证的时候很容易会忽略它的存在,导致应用易受CSRF攻击。所以必须对这个安全问题重视起来。

安全是双方的,需要第三方应用和资源服务提供商均要严格遵守安全规范。如QQ互联的OAuth2API中,state参数是强制必选的参数,授权接口是基于HTTPS的加密通道等;作为第三方开发者在使用消费这些服务的时候也应该重视注意安全中存在的漏洞。

好了,本文到此结束,如果可以帮助到大家,还望关注本站哦!



本文由欣欣吧手游攻略栏目发布,感谢您对欣欣吧的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人站长或者朋友圈,但转载请说明文章出处“移花接木 4.1

标签:
移情别恋电视剧
« 上一篇 2023-10-11