现在的互联网流量入口基本上被几大巨头(BAT、TMD)所把持,对于新上线的应用获取用户比较快捷的方式就是通过OAuth2协议接入它们的账号系统。降低用户注册&登录成本,是大部分新上线应用的选择。比如前段时间吵得沸沸扬扬的抖音滥用腾讯系(微信、QQ)用户信息(头像、暱称)事件,就是因为抖音上线时通过OAuth2接入了腾讯系的账号体系,后面未经腾讯同意就将用户信息给多闪使用。
本文将介绍OAuth2的四种授权模式,重点介绍授权码模式。
下面以用户在第三方应用访问自己的照片列表为例,分别介绍四种授权模式
授权码(authorization-code)
特点
- 安全性高。是OAuth2四种模式中,安全性最高的一种
- 使用率高。据亚马逊统计,互联网上绝大部分应用都使用的是授权码模式,如Facebook、GitHub、微信等
- 流程复杂。是四种模式中最复杂的一种
流程图
详细的授权流程说明
假设
- 第三方应用域名为
https://a.com
- 授权服务器域名为
https://b.com
那么授权流程为:
-
浏览器访问授权服务器请求授权
https://b.com/oauth/auth? response_type=code //表示使用授权码模式 &client_id=CLIENT_ID //第三方应用注册的id &redirect_uri=CALLBACK_URL //用户授权后重定向的地址 &scope=read //授权范围
-
用户手动确认授权
-
授权服务器重定向到指定地址
https://a.com/callback?code=AUTHORIZATION_CODE //code就是授权码
-
第三方应用拿到授权码向授权服务器换取Token
https://b.com/oauth/token? client_id=CLIENT_ID //客户端id &client_secret=CLIENT_SECRET //授权服务器的秘钥 &grant_type=authorization_code //表示使用的是授权码模式 &code=AUTHORIZATION_CODE //授权码 &redirect_uri=CALLBACK_URL //回调的地址
-
当授权服务器校验通过后会向指定的回调地址发送Token信息
{ "access_token":"ACCESS_TOKEN", "token_type":"bearer", "expires_in":2592000, "refresh_token":"REFRESH_TOKEN", "scope":"read", "uid":100101 }
问题
- 与授权服务器的通信协议必须是https吗?
是的。oauth2规范中规定,授权服务器必须是通过加密的https协议进行通信,从而保证与授权服务器通信过程中不会被监听 - 为什么不直接把Token直接给第三方应用,而是通过授权码换区?
如果直接将Token给到浏览器且浏览器与第三方应用通信使用http通信,那么Token将会被窃取且用户无感知 - 既然Token会被窃取,那么授权码就不会被窃取吗?
授权码同样有可能会被窃取。但OAuth2有这样的规定,授权码只能短期有效,且只能换取一次Token,如果获此换取Token,那么以最后一次换取的Token为准。如果黑客在用户之前通过授权码换取了Token,那么用户通过授权码换取Token时,黑客换取的Token将会失效。
简化模式(implicit)
简化模式是相对于授权码模式来说,减少了通过授权码换取Token的步骤
特点
- 简单。流程简单;
- 适用于纯前端应用
- 不安全。稍有不慎,Token可以被恶意脚本获取
- Token有效期短,浏览器关闭即失效
流程图
问题
- 授权码模式中说到直接返回Token不安全,为什么极简模式可以直接返回Token?
返回的Token没有放在queryString中,而是放在fragment(放在#后面)里面。浏览器不会将fragment中的Token带给后端,从而保证不会被别人劫持 - 授权服务器将Token返回到浏览器的过程会不会被别人监听?
不会。因为授权服务器强制使用https协议,所以不会被别人监听
密码模式(password)
特点
- 需要输入账号密码,极度不安全,需要高度信任第三方应用
- 适用于其他授权模式都无法采用的情况
流程图
凭证模式(client credentials)
特点
- 授权维度为应用维度,而不是用户维度。因此有可能多个用户共用一个Token的情况
- 适用于应用维度的共享资源