oAuth流程
对理解OAuth 2.0第六部分授权码模式的自己的分析。
拿使用qq账户登录百度的流程分析下,打开百度,点击登录,然后有qq的图标,点击下,弹出来一个qq的登录页面(现在是扫描二维码的,这里扫描二维码与输入用户密码效果一样)。先确定几个概念:
- 客户端,client,这里指百度,想使用qq的账户获取头像与用户昵称
- 用户,user,资源所有者,资源就是qq头像与用户昵称
- UA,浏览器
- 认证服务器,腾讯的
- 资源服务器,腾讯的,存放用户的头像与昵称
点击qq的头像后弹出来的是qq的登录页面,不是百度的,右键属性,查看下url内容如下:
https://graph.qq.com/oauth2.0/show?which=Login&display=pc&client_id=100312028&response_type=code&display=pc&state=1527595241&redirect_uri=https%3A%2F%2Fpassport.baidu.com%2Fphoenix%2Faccount%2Fafterauth%3Fmkey%3D394f6fab6baf65a164c32282a06c94c2&scope=get_user_info,get_other_info,add_t,add_share
分析下这url
- 首先,是https的,因为可能会输入用户密码,要保证链路的安全。而且因为是在腾讯的页面,所以账户密码百度是获取不到的,这也是oauth主要的出发点
- 然后里面有appid=716027609,这个应该是腾讯分配给百度这个app的一个id,因为这个页面是腾讯的页面,应该是在调用的时候百度自己加进去的id
- redirect_uri这个uri是百度的一个地址,就是在输入qq账号密码后重定向的的地址。因为还是在腾讯的页面
- response_type=code,固定的,oauth的授权码模式
- scope=get_user_info,get_other_info,add_t,add_share,这不是必须的,就是申请权限的内容,这些都是在页面上用户勾选的
输入账户密码后,后面都是腾讯和百度服务器的交互了,看不到交互信息,使用参考文章中的例子,上面是腾讯的页面,输入用户信息后,会发送到认证服务器,然后认证服务器回复的信息可能如下:
HTTP/1.1 302 Found Location: https://baidu.com/cb?code=SplxlOBeZQQYbYS6WxSbIA &state=xyz
- code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。
- state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。相当于使用回调函数的时候使用的userData
然后百度服务器,拿着这个code,并带上自己向腾讯申请的client_secret申请token
POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&client_secret=dafsda &redirect_uri=https%3A%2F%2Fclient%baidu%2Ecom%2Fcb
- grant_type:表示使用的授权模式,必选项,此处的值固定为”authorization_code”。
- code:表示上一步获得的授权码,必选项。
- redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
- client_id:表示客户端ID,必选项。
- client_secret,客户端,也就是百度的密匙
然后腾讯的认证服务器返回token与refresh_token
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":"example", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter":"example_value" }
- access_token:表示访问令牌,必选项。
- token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
- expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
- refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。
- scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。
这里,还有些步骤,比如百度让校验手机号,其实在百度这边,也会单独新建一个用户,然后这个用户里面大概有个类似第三方账户类型值为腾讯,第三方账户的token与refreshtoken的字段,保存着,用来下次获取数据使用。
为什么要用一个授权码code呢?
主要是出于安全的考虑。假如没有这个code的过程,在弹出的腾讯的页面中,输入用户密码后,腾讯的认证服务器直接返回一个token,然后跳转到另外一个百度的页面,百度的这个页面拿着这个token去获取资源。这里token的交互式式直接与web前端交互的,也就是用户的浏览器,token的信息也是在这里面的,oauth认为这样是不够安全的。其实,用了https,已经比较安全了,但是用不用https,oauth并没有强制规定,也可能是因为不是必须https的,所有才有这种code的方式考虑。
oauth认为什么是比较安全的呢?百度服务器到腾讯服务器之间通讯是安全的,而且一般都是https的。