为什么
关于OAuth出现的背景, 在上一篇OAuth1.0介绍 中已经写过了, 而2.0的提出必然是为了解决1.0中出现的问题. 感兴趣的可以去看看. 
2.0针对1.0的问题提出了解决方案, 将协议升级为HTTPS 同时取消了secret加密签名. 对非 web 应用也进行了支持. 
介绍
OAuth是什么呢? 在RFC 文档中是这样介绍的. 
The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf. This specification replaces and obsoletes the OAuth 1.0 protocol described in RFC 5849.
写的比较官方哈, 简单说, 就是授权他人以拥有临时访问资源的权限.
实现
先简单介绍授权过程中涉及到的几个角色:
- 客户端: 既需要申请资源的应用
 - 资源拥有者: 既用户
 - 授权服务器: 通过此服务器获取权限
 - 资源服务器: 通过此服务器进行资源的操作
 
授权流程
在授权之前, 客户端需要先到服务器进行备案, 并拿到身份标识:
- client_id: 用于客户端身份标识
 - client_secret: 用于对请求内容进行签名
 
整个授权流程如下(截图自 RFC 文档):

其中各个步骤的简单说明:
- 客户端向用户申请权限
 - 用户同意进行授权
 - 客户端拿着获得的用户授权, 向授权服务器申请权限令牌
 - 授权服务器通过验证后, 发放权限令牌
 - 客户端时候令牌, 向资源服务器申请资源
 - 资源服务器验证通过后, 返回资源
 
其中的授权服务器和资源服务器只是概念上的拆分, 在实际中可以是同一个服务器(个人感觉这个拆分么的什么用呀).
整个过程使用HTTPS协议进行通信. 其中3-6步, 只是简单的HTTPS请求, 其中比较关键的部分就是用户如何同意授权. 
授权模式
在1.0版本中, 用户的授权是到资源服务器登录并同意授权后, 再通过回调接口的方式通知客户端成功授权的. 当时存在的问题是对非 web 应用不友好. 而在2.0版本中, 为了应对多种场景, 给出了四种不同的授权模式. 
授权码
授权码模式就是客户端先拿到一个授权码, 然后使用授权码到授权服务器获取授权令牌. 与1.0的授权方式差不多. 
这里就不用 RFC 文档中的图了, 换一张我画的感觉更简洁一些.

看这个流程, 其实和1.0版本的流程差不多. 对以上几步简单说明. 
1. 重定向到服务器授权页面
将用户引导到授权服务器进行授权操作.
携带参数
- response_type: 请求类型, 值为 code, 标识为授权码模式
 - client_id: 客户端 ID. 用于标识客户端身份
 - redirect_uri: 用户授权成功后, 通知的回调链接.
 - scope: 用于标识需要申请的权限.
 
2. 用户在 授权服务器完成授权操作
用户在授权服务器页面进行登录授权.
3. 将页面重定向到事先指定的链接, 带上授权 code
用户授权完成后, 授权服务器将页面重定向到第一步中的redirect_uri, 通知客户端授权结果. 在进行跳转时会带上授权成功后的授权码. 
4. 使用授权 code 获得令牌 access_token
用户成功授权并拿到授权凭证后, 想授权服务器申请access_token. 
携带参数
- client_id
 - client_secret: 因为当前请求是由后端发起, 不会经过客户端, 因此不会泄露.
 - grant_type: 授权方式. authorization_code(表示授权码)
 - code: 上一步获取的授权码
 
到这一步, 已经完成整个授权流程.
简化版
有些网站是纯前端的, 没有后端. 这种方式直接向前端颁发授权令牌, 省去了授权码这个步骤.

1. 重定向到服务器授权页面
将用户引导到授权服务器进行授权操作.
携带参数
- response_type: 请求类型, 值为 token, 表示直接返回token
 - client_id: 客户端 ID. 用于标识客户端身份
 - redirect_uri: 用户授权成功后, 通知的回调链接.
 - scope: 用于标识需要申请的权限.
 
2. 用户在 授权服务器完成授权操作
用户授权操作没有什么差别.
3. 将页面重定向到回调链接并携带授权 token
因为没有后端服务器, 因此授权成功后直接在重定向链接中带有授权 token. 链接形式: https://test.com/callback#token=ACCESS_TOKEN
注意, 这里access_token是以锚点的形式拼在回调链接上的. 因为浏览器在访问的时候, 不会将锚点发送, 因此可以避免中间人攻击. 
以这种方式获取的令牌往往授权时间比较短, 通常就是 session 期间有效.
密码版
这就是原始的版本了, 将你的用户名和密码直接告诉客户端, 然后客户端使用你的密码去申请令牌.

客户端获取 token 时携带的参数如下:
- grant_type: 授权类型. (password)
 - username
 - password
 - client_id
 - scope
 
授权服务器校验后会返回授权令牌. 注意, 一般在第一步获取用户名和密码时, 客户端并不对其进行存储, 仅仅是在第二步获取授权时使用.
客户端模式
适用与没有交互界面的应用. 授权过程中没有用户参与, 客户端直接申请 token.

携带参数
- grant_type: 授权类型(client_credentials)
 - client_id
 - client_secret
 
授权服务器校验后直接返回access_token. 看这个模式并不是OAuth想要解决的问题啊, 看不懂为什么放在这里
令牌更新
OAuth2.0允许在令牌过期后, 不经过用户进行令牌的更新. 授权服务器在颁发令牌时, 会同时颁发两个令牌: access_token refresh_token. 
其中refresh_token的过期时间要更久一些, 用于当access_token过期后对其进行更新.