????????OAuth2是一个开放的授权标准,允许第三方应用程序以安全可控的方式访问受保护的资源,而无需用户将用户名和密码信息与第三方应用程序共享。OAuth2被广泛应用于现代Web和移动应用程序开发中,可以简化应用程序与资源服务器之间的授权过程,提高应用程序的安全性。
OAuth2的基本工作原理如下:
案例解读:
用户授权第三方应用程序访问其社交媒体账户
- 用户在第三方应用程序中点击“登录”或“授权”按钮。
- 第三方应用程序将用户重定向到社交媒体平台的授权页面。
- 用户在授权页面上输入其社交媒体账户的用户名和密码(或扫码),并点击“授权”。
- 社交媒体平台会向用户展示授权详细信息,如应用程序名称、权限范围等,并要求用户确认授权。
- 用户点击“确认授权”后,社交媒体平台会向第三方应用程序颁发一个访问令牌(Access Token)。
- 第三方应用程序将访问令牌存储起来,并使用该访问令牌来访问社交媒体平台上的受保护资源,如用户个人信息、社交分享、好友列表等。
????????在这个案例中,第三方应用程序是OAuth2的客户端应用程序,社交媒体平台是OAuth2的资源服务器,用户是OAuth2的资源所有者。OAuth2服务器是社交媒体平台提供的服务,负责颁发访问令牌。
OAuth2的工作流程可以总结为以下几个步骤:
- 客户端应用程序请求用户授权。
- 用户授权后,客户端应用程序向OAuth2服务器请求访问令牌。
- OAuth2服务器颁发访问令牌给客户端应用程序。
- 客户端应用程序使用访问令牌访问资源服务器上的受保护资源。
????????OAuth2通过将用户密码信息与第三方应用程序隔离,提高了应用程序的安全性。同时,OAuth2是一个开放的标准,可以与不同的应用程序、平台和设备兼容,易于理解和使用,可以快速集成到应用程序中。
OAuth2.0
?的授权简单理解其实就是获取令牌(token
)的过程,OAuth
?协议定义了四种获得令牌的授权方式(authorization grant
?)如下:
authorization-code
)implicit
)password
):client credentials
)????????但值得注意的是,不管我们使用哪一种授权方式,在三方应用申请令牌之前,都必须在系统中去申请身份唯一标识:客户端 ID(client ID
)和 客户端密钥(client secret
)。这样做可以保证?token
?不被恶意使用。授权码模式和密码模式比较常用。
????????授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。 ?
OAuth2.0
四种授权中授权码方式是最为复杂,但也是安全系数最高的,比较常用的一种方式。这种方式适用于兼具前后端的Web
项目,因为有些项目只有后端或只有前端,并不适用授权码模式。
利用qq登录扫码授权示例:
请求示例:
(A)步骤:客户端申请认证的URI
https://graph.qq.com/oauth2.0/show?which=Login
&display=pc
&scope=get_idollist%2Cget_fans……
&response_type=code
&redirect_uri=https%3A%2F%2Fpassport.iqiyi.com%2……
&client_id=xxxx
&state=ZOvw70n5zJtY1H%2……
参数说明:
参数类型 | 说明 |
---|---|
response_type | 授权类型,必选项,此处的值固定为"code" |
client_id | 客户端的ID,必选项 |
redirect_uri | 重定向URI,认证服务器接受请求之后的调转连接,可以根据这个连接将生成的授权码回传,必选项 |
scope | code发送给资源服务器申请的权限范围,可选项 |
state | 任意值,认证服务器会原样返回,用于抵制CSRF(跨站请求伪造)攻击。 |
(B)步骤:用户·确认授权
(C)步骤:服务器回应客户端的URI
https://graph.qq.com//client.example.com/cb?code=SplxlOBeZQQ&state=xxx
参数说明:
参数类型 | 说明 |
---|---|
code | 授权码,必选项。授权码有效期通常设为10分钟,一次性使用。该码与客户端ID、重定向URI以及用户,是一一对应关系。 |
state | 原样返回客户端传的该参数的值 |
(D)步骤:客户端向认证服务器申请令牌
参数说明:
参数类型 | 说明 |
---|---|
client_id | 表示客户端ID,必选项 |
client_secret | 表示安全参数,只能在后端发请求 |
grant_type | 表示使用的授权模式,必选项,此处的值固定为"authorization_code" |
code | 表示上一步获得的授权码,必选项 |
redirect_uri | 表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致 |
(E)步骤:响应(D)步骤的数据
{?
?? ?"access_token":访问令牌,?
?? ?"token_type":"bearer",?
?? ?"expires_in":过期时间,?
?? ?"refresh_token":"REFRESH_TOKEN",?
?? ?"scope":"read",?
?? ?"uid":用户ID,
? ? "info":{...}?
}
参数说明:
参数类型 | 说明 |
---|---|
access_token | 访问令牌,必选项 |
token_type | 令牌类型,该值大小写不敏感,必选项 |
expires_in | 过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间 |
refresh_token | 更新令牌,用来获取下一次的访问令牌,可选项 |
scope | 权限范围,如果与客户端申请的范围一致,此项可省略 |
如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。
在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而授权服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
适用场景:公司搭建的授权服务器
(A)用户向客户端提供用户名和密码。
(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。
(C)认证服务器确认无误后,向客户端提供访问令牌。
?客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行 授权。
适用于没有前端的命令行应用,即在命令行下请求令牌。一般用来提供给我们完全信任的服务器端服务。
(A)客户端向认证服务器进行身份认证,并要求一个访问令牌。
(B)认证服务器确认无误后,向客户端提供访问令牌。
一些具体的客户端凭证模式的使用场景包括:
- 物联网设备:?物联网设备通常需要连接到云平台来发送数据和接收指令。可以使用客户端凭证模式来获取访问令牌,而不需要用户登录。
- 智能家居设备:?智能家居设备通常需要连接到云平台来接收指令和控制其他智能家居设备。可以使用客户端凭证模式来获取访问令牌,而不需要用户登录。
- 可穿戴设备:?可穿戴设备通常需要连接到云平台来同步数据和接收指令。可以使用客户端凭证模式来获取访问令牌,而不需要用户登录。
- 后台数据处理任务:?后台数据处理任务通常需要访问某个API来获取数据或处理数据。可以使用客户端凭证模式来获取访问令牌,而不需要用户登录。
- 服务集成:?两个服务之间需要集成,可以使用客户端凭证模式来获取访问令牌,而不需要用户登录。
????????有些 Web 应用是纯前端应用,没有后端。必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌,这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。跳过授权码,qq授权通过后重定向到指定?redirect_uri
?。
https://graph.qq.com/oauth2.0/authorize?
? response_type=token&
? client_id=CLIENT_ID&
? redirect_uri=http://juejin.im/callback&
? scope=read
隐藏式不通过第三方应用程序的服务器,直接在浏览器中向授权服务器申请令牌,跳过了"授权码"这个步骤,所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。