是什么
- 开放授权,令牌token代替密码访问。
- 其实就是授权登录,允许通过其他平台的账号去登录另一平台,比如用QQ登录豆瓣。
- OAuth实际是一种授权的协议,只要授权方和被授权方遵守这个协议去写代码提供服务,那双方就是实现了OAuth模式。
- 允许用户让第三方应用反问该用户在另一平台上存储的资源(如照片、视频。联系人列表),而无需向第三方应用透露用户名和密码。
- 举个栗子,你不曾在豆瓣注册账号,但是又想登录豆瓣,那么你可以把你的QQ号授权给豆瓣登录。
- 在豆瓣点击QQ登录:
- 跳转到QQ登录页面输入信息,点击授权并登录:
- 跳回豆瓣页面,登录成功:
上述例子中的豆瓣就是客户端,QQ就是认证服务器,OAuth2.0就是客户端和认证服务器之间由于相互不信任而产生的一个授权协议。(要是信任的话QQ岂不是要把数据库整个交给豆瓣去做用户验证。)
为什么不直接在豆瓣输入账号密码然后去QQ哪里获取用户数据呢?因为这样做有很多严重的缺点,其中一点就是豆瓣需要明文保存用户的账号和密码,这样很不安全,而且只要有一个类似豆瓣的平台被破解,就会导致用户信息泄露。
OAuth2角色
- 资源所有者Resource Owner
- 资源服务器Resource Server
- 授权服务器Authorization Server
- 客户端Client
资源所有者
- 代表授权给客户端来访问本身资源信息的用户,也就是以上例子中要登录豆瓣的用户。
资源/授权服务器
- 资源服务器托管了受保护用户的账号信息,而授权服务器验证用户身份然后为客户端派发访问令牌Token。
- 在上述例子中,QQ既是资源服务器(个人信息和通讯录等即为资源),也是授权服务器。而实际上不同服务器往往独立部署。协同保护用户账户信息资源。
客户端
- 意图访问受限资源的第三方应用。在访问之前,它必须先经过用户授权,获取授权凭证Grant,进一步由授权服务器进行验证。
授权流程
第一步中的Grant有4中type:
- Authorization Code:授权码模式,功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与验证服务器进行互动。
- implicit grant type:简化模式。
- Resource Owner Password Credentials Grant:密码模式。
- Client Credentials Grant:客户端模式。
以授权码模式具体到上述例子流程为:
- 在豆瓣官网点击用QQ登录的小图标时,实际上是向豆瓣的服务器发起了一个http://www.douban.com/leadToAuthorize的请求。
- 豆瓣服务器响应一个重定向地址http://www.qq.com/authorize?client_id=123050457758183callback=www.douban.com/callback,指向QQ授权登录,其中client_id参数为豆瓣事先在QQ注册的应用id,callback参数则是QQ登录成功后浏览器能找到原始要访问的地址。
- 浏览器接收到这个重定向地址后向qq服务器发起授权请求。
- 蓝色箭头:QQ服务器接收到豆瓣发来的authorize,响应以qq登录页面,要求浏览器提供用户许可。
- 黄色箭头:用户输入信息后提交表单给QQ服务器。
- QQ服务器验证成功后会响应浏览器一个重定向地址,并附带一个授权码code。
- 浏览器接收到重定向地址,发起请求http://www.douban.com/callback?code=2559200ecd7ea433f067a2cf67d6ce6c。
- 豆瓣服务器收到请求后,用拿到的code模拟浏览器向qq服务器索取token。获取token十分重要,一般采用post,请求token的url为POST https://api.qq.com/oauth2/getToken,包含如下参数:
- client_id:应用id。
- client_secret:在应用OAuth2之前,必须在授权方服务中注册你的应用,QQ就是一个OAuth实现平台,开发者向它提供应用名称(豆瓣)、应用网站和回调url。注册成功后,授权方服务将以client_id和client_secret的形式为应用发布client credentials(客户端凭证)。client_id是公开的、用于识别应用程序的唯一标识,client_secret用于验证应用身份,并且在客户端和服务之间保持私有性。
- grant_type: 值为“authorization_code”,即许可类型。
- code:上一步获得的code。
- redirect_url:回调地址。
- QQ服务器返回token:
//参数用json返回,且头信息中会明确指定不许缓存
{
"access_token": "ACCESS_TOKEN",//Token 的值
"expires_in": 1234,//过期时间;过期后需重新授权登录,
或使用refresh_token重新申请(一般用在不间断连续在线)
"uid":"12341234"//当前授权用户的账号id。
}
- 再用拿到的token索取用户信息,如获取用户昵称和头像:
GET https://api.weibo.com/2/users/show.json?access_token&uid - qq服务器返回用户信息。
- 最后将用户信息存储起来,返回给浏览器首页。到此OAuth2.0授权结束。
实现
- 现有的Java版的对OAuth2协议的实现有:
- 资料较多的是Apache oltu和spring security aouth,因为是开源的。
- oltu更轻量、更简单,是对OAuth2的简单实现,很多后续校验的事情都需要我们自己去做,但这也是它灵活的一面。