我的博客地址:blog.sqdyy.cnhtml
OAuth2要解决的问题
开放系统间受权问题
OAuth2最初是基于开放系统间受权问题提出的,假设如今有一个第三方应用:“云冲印服务”,能够将用户存储在Google的照片冲印出来。用户为了使用该服务,必须让“云冲印服务”读取本身储存在Google上的照片。问题是只有获得用户的受权,Google才会赞成“云冲印服务”读取这些照片。那么“云冲印服务”如何获取用户的受权呢?前端
办法1:密码用户名复制
传统的办法是,资源拥有者将本身的用户名和密码告诉第三方服务,而后第三方服务再去读取用户受保护的资源,这种作法适用于公司内部应用开发时使用,在开放系统间这么作就不太合适了,由于第三方服务可能为了后续的服务,会保存用户的密码,这样很不安全。web
办法2:万能钥匙
另外一种方法是客户应用和受保护的资源之间商定一个通用developer key,用户在受保护资源方获得一个developer key交给第三方应用,第三方应用再经过这个developer key去访问用户受保护的资源。这种方式适用客户应用和受保护资源之间存在信任关系的状况,如两方是合做商,或是同个公司不一样部门之间的应用。可是对于不受信的第三方应用来讲这种方法也不合适。数据库
办法3:特殊令牌
第三种方法是使用一个特殊令牌,它仅仅能访问受保护的资源,这种作法相对前两种方法要靠谱的多,而且和OAuth2的作法已经比较接近了,可是如何管理令牌,颁发令牌,吊销令牌就须要一些讲究了,这些咱们留到后面介绍OAuth2再来了解。后端
现代微服务安全问题
传统单块应用的架构中,一般咱们的单块应用会部署到应用服务器作成集群,其中会有一个专门用于处理登陆受权的用户数据库。当用户访问应用服务器时,会经过应用的拦截器进行拦截鉴权,若是鉴权登陆成功,一般由服务器发给客户端一个会话标识Session ID,客户端将Session ID存储在Cookie中,服务器记录Session ID与通过验证的用户的对应关系。浏览器
相对而言,传统单块应用主要是直接面向PC用户的Web应用,对于现代微服务架构而言,上面的作法就不适用了。对于现代微服务架构而言,服务之间拆分的粒度较小,须要考虑服务和服务之间的鉴权问题,另外就是应用的形态变得多种多样,例若有单页应用,无线原生APP,服务端APP。这种场景下咱们一般会设计一个独立的服务,将认证和受权都作成一个AuthServer,经过Token的形式进行鉴权和受权,那么这也是OAuth2解决的一个主要问题,咱们将在后面进行介绍。安全
OAuth的基本概念
OAuth2.0是用于REST/APIs的代理受权框架(delegated authorization framework),它基于令牌Token的受权,在无需暴露用户密码的状况下,使应用能获取对用户数据的有限访问权限。Oauth2.0能将认证和受权解耦,它是事实上的标准安全框架,支持多种应用场景,如服务端WebApp,浏览器单页应用SPA,无线/原生App,服务器对服务器之间调用等等。服务器
OAuth2.0具备如下优点:session
- 客户端不接触用户密码,服务端更易集中保护
- 普遍传播并被持续采用
- 支持短寿命和封装的Token
- 资源服务器和受权服务器解耦
- 集中式受权,简化客户端
- HTTP/JSON友好,易于请求和传递Token
- 考虑多种客户端架构场景
- 客户端能够具备不一样的信任级别
OAuth2.0的不足:架构
- 协议框架太宽泛,形成各类实现的兼容性和互操做性差
- 和OAuth1.0不兼容
OAuth须要注意的地方:
- OAuth并无支持HTTP之外的协议。
- OAuth并非一个认证协议。
- OAuth并无定义受权处理机制。
- OAuth并无定义Token类型。
- OAuth2.0并无定义加密方法。
- OAuth2.0并非单个协议。
- OAuth2.0仅是受权框架,仅用于受权代理。
OAuth主要角色和术语
- Client Application(客户应用):一般是一个Web或者无线应用,它须要访问用户的受保护资源。
- Resource Server(资源服务器):是一个Web站点或者Web service API,用户的受保护数据保存在此。
- Authorized Server(受权服务器):在客户应用成功认证并得到受权以后,向客户应用颁发访问令牌Access Token。
- Resource Owner(资源拥有者):资源的拥有人,想要分享某些资源给第三方应用。
- Client Credentials(客户凭证):客户的clientId和密码用于认证客户。
- Tokens(令牌):受权服务器在接收到用户请求之后,颁发访问令牌。
- Scopes(做用域):客户请求访问令牌时。由资源拥有者额外指定细分权限(permission)
OAuth令牌类型
令牌Token是OAuth2.0的核心概念,令牌能够类比为一把仆从钥匙(Valet Key),它给应用受权有限的访问权限,让应用可以表明用户去访问用户的数据。
- Authorization Code Token(受权码):仅用于受权码受权类型,用于交换获取访问令牌和刷新令牌。
- Refresh Token(刷新令牌):用于去受权服务器获取一个新的令牌。
- Access Token(访问令牌):用于表明一个用户或服务直接去访问受保护的资源。
- Bearer Token:不论是谁拿到Token均可以访问资源。
- Proof of Possession(Pop) Token:能够校验client是否对Token有明确的拥有权。
OAuth2受权方式
先来看OAuth2.0的运行流程:
- (A)用户打开客户端之后,客户端要求用户给予受权。
- (B)用户赞成给予客户端受权。
- (C)客户端使用上一步得到的受权,向认证服务器申请令牌。
- (D)认证服务器对客户端进行认证之后,确认无误,赞成发放令牌。
- (E)客户端使用令牌,向资源服务器申请获取资源。
- (F)资源服务器确认令牌无误,赞成向客户端开放资源。
这里的B步骤是关键,即客户如何给客户的受权,有了这个受权后客户端就能够获取令牌,进而凭借令牌获取资源,OAuth2.0为咱们提供了4种客户端获取受权的模式:
- 受权码模式(Authorization Code)
- 简化模式(implicit)
- 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
受权码模式
受权码模式相对其余三个模式来讲是功能最完整,流程最安全严谨的受权方式。它的特色是经过客户端的后台服务器与服务提供商的认证服务器进行交互:
它的步骤以下:
- (A)用户访问客户端,客户端将用户导向认证服务器,须要携带客户端ID凭证和重定向URI。
- (B)用户选择是否给予客户端受权。
- (C)假设用户给予受权,认证服务器将用户导向事先指定的重定向URI,同时附上一个受权码。
- (D)客户端收到受权码后,在后台服务器(对用户不可见)携带事先指定的重定向URI和受权码向认证服务器申请令牌。
- (E)认证服务器核对受权码和重定向URI,确认无误后,向客户端颁发访问令牌(access token)和刷新令牌(refresh token)。
简化模式
简化模式不经过服务端程序来完成,比受权码模式减小了“受权码”这个步骤,直接由浏览器发送请求获取令牌,令牌对访问者是可见的,且客户端不须要认证,这种模式通常用于单页应用:
它的步骤以下:
- (A)用户访问客户端,客户端将用户导向认证服务器,须要携带客户端ID凭证和重定向URI。
- (B)用户选择是否给予客户端受权。
- (C)假设用户给予受权,认证服务器将用户导向事先指定的重定向URI,并在URI的Hash部分包含了访问令牌(Fragment)。
- (D)浏览器向资源服务器发出请求,其中不包含事先收到的Hash部分(Fragment)。
- (E)资源服务器返回一段脚本,其中包含的代码能够获取Hash部分中的令牌。
- (F)浏览器执行事先获取的脚本,提取出令牌
- (G)浏览器将令牌发送给客户端。
密码模式
密码模式中,用户向客户端提供用户名和密码,客户端使用这些信息,直接向认证服务器索要受权。这种模式违背了前面提到的微服务安全要解决的问题(不暴露用户名和密码),可是在一些用户对客户端高度信任的状况下,例如公司内部软件间的受权下,使用这种模式也是适用的:
它的步骤以下:
- (A)用户向客户端提供用户名和密码。
- (B)客户端将用户名和密码发送给认证服务器,向认证服务器索要令牌。
- (C)认证服务器确认无误后,向客户端提供访问令牌。
客户端模式
客户端模式是客户端以本身的名义去受权服务器申请受权令牌,并非彻底意义上的受权。主要应用于Docker到DokcerHub拉取镜像的这类场景:
它的步骤以下:
- (A)客户端向认证服务器进行身份认证,并要求获取访问令牌。
- (B)认证服务器确认无误后,向客户端提供访问令牌。
刷新令牌
若是用户访问的时候,客户端的"访问令牌"已通过期,则须要使用"更新令牌"申请一个新的访问令牌:
它的步骤以下:
- (A)客户端向认证服务器进行身份认证,并要求获取访问令牌。
- (B)认证服务器确认无误后,返回访问令牌和一个刷新令牌。
- (C)客户端经过访问令牌访问受保护资源。
- (D)若是访问令牌未过时,则向客户端提供资源服务。
- (E)客户端经过访问令牌访问受保护资源。
- (F)若是访问令牌过时,受保护资源服务器返回Invalid Token Error。
- (G)客户端获得上方的错误后,经过刷新令牌向受权服务器申请一个新的访问令牌。
- (H)认证服务器确认无误后,返回访问令牌和一个刷新令牌。
OAuth2.0四种模式的选型
上面介绍了OAuth4种客户端受权模式,下面介绍这4种模式的技术选型,在这以前先作两个概念铺垫:
受权流程渠道(channels): 前面提到了OAuth2的四个主要角色,这四个角色之间的交互能够划分红两类渠道,凡是资源拥有者、客户应用和受权服务器之间的发送交互能够划分为 前端渠道。凡是受权服务器、客户应用和资源服务器之间发生的交互能够划分为后端渠道。
客户应用类型:客户应用也能够划分为两类应用,第一类是公开应用,主要是指单页应用SPA或原生App应用,这类应用都是驻在用户手中的,这种应用不能将用户的凭证信息如密码驻留在上面,通常只存用户标识。第二类是私密应用,主要指Web服务端应用、服务/API(机器对机器间),这种应用是在后端运行的,总体上相对安全,能够驻留用户凭证信息。
四种OAuth2.0受权模式的特征
在选型以前咱们先来汇总一下四种受权类型的特征:
受权码模式
- 经过前端渠道客户获取受权码
- 经过后端渠道,客户使用受权码去交换访问令牌和刷新令牌
- 假定资源拥有者和客户在不一样设备上
- 最安全的流程,由于令牌不会传递通过user-agent
简化模式
- 适用于公开的浏览器单页应用
- access token直接从受权服务器返回(只有前端渠道)
- 不支持refresh token
- 假定资源全部者和公开应用在同一个应用上
- 最容易受到安全攻击
用户名密码模式
- 使用用户名密码登陆的应用,例如桌面App,内部软件
- 使用用户名/密码做为受权方式从受权服务器上获取access token
- 通常不支持refresh token
- 假定资源拥有者和公开用户在相同设备上
客户端模式
- 适用于服务器间通讯厂家,机密客户表明它本身或者一个用户
- 只有后端渠道,使用客户凭证获取一个access token
- 由于客户凭证可使用对称或非对称加密,该方式支持共享密码或者证书
受权模式选型
综合上述,在选型时能够参考下面流程图的思路:
本文参考资料: