最近工做中遇到了多系统间的受权登陆,对OAuth2.0进行了学习研究,并总结备忘。sql
咱们登陆一些论坛等网站的时候,若是不想单独注册该网站帐号,能够选择用微信或QQ帐号进行受权登陆。 这样的第三方登陆方式究竟是怎么实现的呢?难道是腾讯把咱们微信或QQ帐号信息卖给了这些网站?很显然,腾讯是不会这么干的,这种登陆方式的实现,其实就是使用的OAuth2.0的受权登陆方式。 json
相似地,在公司内部,若是公司有多套不一样的软件系统,例如公司内网的财务报销系统、考勤系统、报销系统、人事系统等,也能够实现一个员工帐号就能受权访问全部系统,而不须要每一个系统都开通单独的帐号,设置独立的密码。这是一般所说的SSO单点登陆,而OAuth2.0是单点登陆的实现方式之一。 后端
OAuth2.0是一种容许第三方应用程序使用资源全部者的凭据得到对资源有限访问权限的一种受权协议。浏览器
例如在上述例子中,经过微信登陆论坛的过程,就至关于微信容许该论坛做为第三方应用程序在通过微信用户受权后,经过微信颁发的受权凭证有限地访问用户的微信头像、手机号,性别等受限制的资源,从而来构建自身的登陆逻辑。安全
注:在OAuth2.0协议中,第三方应用程序获取的凭证并不等同于资源拥有者持有的用户名和密码,以上面例子来讲,微信是不会直接将用户的用户名、密码等信息做为凭证返回给该论坛的。这种受权访问凭证通常来讲就是一个表示特定范围、生存周期和其访问权限的一个由字符串组成的访问令牌,也就是咱们常说的token。在这种模式下OAuth2.0协议中经过引入一个受权层来将第三方应用程序与资源拥有者进行分离,而这个受权层也就是常说的“auth认证服务/sso单点登陆服务器”。 服务器
在OAuth2.0协议中定义了如下四个角色: 微信
1)resource owner(资源拥有者)app
即可以有权授予对保护资源访问权限的实体。例如咱们使用经过微信帐号登陆论坛,而微信帐号信息的实际拥有者就是微信用户,也被称为最终用户。 学习
2)resource server(资源服务器)网站
承载受保护资源的服务器,可以接收使用访问令牌对受保护资源的请求并响应,它与受权服务器能够是同一服务器(下述的“简化模式”),也能够是不一样服务器(下述的“受权码模式”)。在上述例子中该角色就是微信服务器。
3)client(客户端)
表明资源全部者及其受权发出对受保护资源请求的应用程序。在上面的例子中的用户要注册的论坛就是该角色。
4)authorization server(受权服务器)
认证服务器,即服务提供商专门用来处理认证受权的服务器。例如微信开放平台提供的认证服务的服务器。
仍是以微信受权登陆举例,流程以下:
流程说明:
在上述流程中比较关键的动做是resource owner(资源拥有者,用户)怎么样才能给Client(豆瓣网论坛)受权,由于只有有了这个受权,Client角色才能够获取访问令牌(access_token),进而经过令牌访问其余资源接口。而关于客户端如何得到受权的问题,在OAuth2.0中定义了四种受权方式,目前微信受权登陆,使用的就是其中最经常使用的一种:“受权码模式”(authorization_code)。
OAuth2.0定义了四种受权模式,它们分别是:
四种模式对比说明:
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请求,包含如下参数:
示例: 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请求,包含如下参数:
示例: 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