Open Cuuube opened 6 years ago
这周项目上用到了需要获取第三方用户权限来授权登陆我们网站。用到的技术是oauth2。
一遍看文档,一遍写demo,花了一天终于搞清了其中奥妙。所以赶紧记录下来,给健忘的自己。
oauth是个什么呢?
推荐阅读:理解OAuth 2.0 —— 阮一峰
我的这篇文章也是从阮大大那里反刍而成。并且不一定有阮大大写的全面且通俗易懂。希望大家一定看看。
简单来说,oauth2.0,规范了一套授权的流程。它是被广泛验证而且应用的。如果大家都按照这个流程来执行验证,可以减少很多代码量。
前面也说了,oauth2.0只是一套流程和接口的规范。
所以毫不客气的说,oauth就是一堆api调来调去,只要你会服务器端http请求,和一点浏览器前端知识,你就能自己完成一套从授权者到请求授权者的全部代码。
那么我们现在来扒一扒都有哪些api,怎么调。
在调用之前,需要先声明几个角色:
我们就以第三方登陆为例,设定以下场景:
网站A接入了网站B,允许用户在网站A上点击“用XX登陆”来使用用户在网站B上的身份信息来登陆网站A(如同一般网站上的用QQ登陆)。
此时网站A扮演Requester,网站B扮演DataOwner。用户自己是User。
开始展开调用。
用户点击了网站A上的XX登陆。一般而言,会先跳转到网站A上的某条路由。
如/oauth/login/B
/oauth/login/B
然后此路由中代码收到消息:有匿名用户希望用用户在B上的资料登陆。
按照规则,网站A开始扮演Requester的角色。他需要联系DataOwner,开始请求数据。
此请求一般为redirect,并且通常请求uri中带有authorize。
authorize
直接拿阮大大文中的例子:
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
发送的字段一般含有如下:
response_type:表示授权类型,必选项,此处的值固定为"code" client_id:表示客户端的ID,必选项 state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。 redirect_uri:表示重定向URI,可选项 scope:表示申请的权限范围,可选项
其中client_id是DataOwner提前商定给Requester的一个定值,代表Requester方有获取DataOwner中用户内容的权限。
此时,用户界面已经被重定向到DataOwner服务器那里。此阶段对用户不可见,用户那里只看到浏览器url变了,然后在转圈圈。
此时,DataOwner处理完毕上一步,发送重定向给用户,到自己的登陆页面。
用户会看到界面变为了网站B的登陆页面。需要输入自己在网站B的账户密码。
当用户输入完毕后,便离开了网站B的登陆页,暂时又开始转圈圈。
而DataOwner角色此时收到了用户登陆信息,确认完毕电脑前这个生物是自己的用户,会生成一个字符串,作为用户授权码。
还记得第二步吗?Requester请求authorize接口时,带了一个redirect_uri字段。此时它有用了。
redirect_uri
DataOwner会用get请求,请求redirect_uri给的uri。用这种方式,把信息传回给Requester。
这个请求会带上如下字段:
code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。 state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。
此时对于用户而言,刚刚输入完毕B网站的登陆信息后,被跳转到了之前的网站A。然后再等待响应。这状态一直持续的本文的第十步。
Requester需要提前写好这条redirect_uri的callback路由,以接收code和state。
当callback路由接收到之后,就可以向DataOwner请求令牌(token)了。
请求令牌的uri通常带有token字样。
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 &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
这次索取token的请求,通常带有如下参数:
grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。 code:表示上一步获得的授权码,必选项。 redirect_uri:表示重定向URI,必选项,且必须与上一步的该参数值保持一致。 client_id:表示客户端ID,必选项。
很容易理解。
DataOwner收到请求,会验证一下用户授权码(code)的真伪,是不是由自己发出的。当验证成功,就可以响应了。token的响应通常是如下字段:
access_token:表示访问令牌,必选项。 token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。 expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。 refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。 scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。
DataOwner角色注意,响应头中必须设置本响应不允许缓存。因为access_token通常是一次性的。被缓存会影响下次的请求。
现在Requester收到了token了。已经证明了自身的纯洁,和用户的意愿。既然你来我往都自愿,那就可以大大方方地索取用户的数据了。
向DataOwner的用户数据路由请求就不是oauth2.0负责规范的范围了。但一定要带上刚刚获取的token吧?下面是个简单的例子:
POST /user_info?access_token=xxxxxxxxxxxxxxx HTTP/1.1
DataOwner验证自己发送的令牌真伪。如属真,则响应用户信息。
至于响应哪些用户信息,就通常是各家不同,看DataOwner角色提供的接入文档了。
得到了用户的信息,这一步也没什么好说的。可以把用户信息存进自己的数据库注册用户。
(如目的不是第三方登陆,只是请求一部分资料,则可以拿资料接下来的事。)
恭喜恭喜,用户终于看到页面动了,页面转到网站A,并且此时自己已经被注册为网站A的会员了。
终于达成了用户用网站B的信息来注册网站A的会员这一战略目的。
最后——感谢阮一峰大大!
对oauth2登陆的总结
前言
这周项目上用到了需要获取第三方用户权限来授权登陆我们网站。用到的技术是oauth2。
一遍看文档,一遍写demo,花了一天终于搞清了其中奥妙。所以赶紧记录下来,给健忘的自己。
简介
oauth是个什么呢?
推荐阅读:理解OAuth 2.0 —— 阮一峰
我的这篇文章也是从阮大大那里反刍而成。并且不一定有阮大大写的全面且通俗易懂。希望大家一定看看。
简单来说,oauth2.0,规范了一套授权的流程。它是被广泛验证而且应用的。如果大家都按照这个流程来执行验证,可以减少很多代码量。
oauth2.0的流程
前面也说了,oauth2.0只是一套流程和接口的规范。
所以毫不客气的说,oauth就是一堆api调来调去,只要你会服务器端http请求,和一点浏览器前端知识,你就能自己完成一套从授权者到请求授权者的全部代码。
那么我们现在来扒一扒都有哪些api,怎么调。
在调用之前,需要先声明几个角色:
我们就以第三方登陆为例,设定以下场景:
网站A接入了网站B,允许用户在网站A上点击“用XX登陆”来使用用户在网站B上的身份信息来登陆网站A(如同一般网站上的用QQ登陆)。
此时网站A扮演Requester,网站B扮演DataOwner。用户自己是User。
开始展开调用。
第一步:用户点击网站A上的XX登陆按钮
用户点击了网站A上的XX登陆。一般而言,会先跳转到网站A上的某条路由。
如
/oauth/login/B
然后此路由中代码收到消息:有匿名用户希望用用户在B上的资料登陆。
按照规则,网站A开始扮演Requester的角色。他需要联系DataOwner,开始请求数据。
第二步: Requester向DataOwner索要User的身份授权
此请求一般为redirect,并且通常请求uri中带有
authorize
。直接拿阮大大文中的例子:
发送的字段一般含有如下:
其中client_id是DataOwner提前商定给Requester的一个定值,代表Requester方有获取DataOwner中用户内容的权限。
此时,用户界面已经被重定向到DataOwner服务器那里。此阶段对用户不可见,用户那里只看到浏览器url变了,然后在转圈圈。
第三步:DataOwner让User输入身份信息,确认身份
此时,DataOwner处理完毕上一步,发送重定向给用户,到自己的登陆页面。
用户会看到界面变为了网站B的登陆页面。需要输入自己在网站B的账户密码。
当用户输入完毕后,便离开了网站B的登陆页,暂时又开始转圈圈。
第四步:DataOwner确认User身份,确认User同意将身份信息给Requester使用,于是向Requester发送请求,带上用户授权码
而DataOwner角色此时收到了用户登陆信息,确认完毕电脑前这个生物是自己的用户,会生成一个字符串,作为用户授权码。
还记得第二步吗?Requester请求
authorize
接口时,带了一个redirect_uri
字段。此时它有用了。DataOwner会用get请求,请求
redirect_uri
给的uri。用这种方式,把信息传回给Requester。这个请求会带上如下字段:
此时对于用户而言,刚刚输入完毕B网站的登陆信息后,被跳转到了之前的网站A。然后再等待响应。这状态一直持续的本文的第十步。
第五步:Requester收到用户授权码,向DataOwner请求令牌(token)。
Requester需要提前写好这条
redirect_uri
的callback路由,以接收code和state。当callback路由接收到之后,就可以向DataOwner请求令牌(token)了。
请求令牌的uri通常带有
token
字样。例:
这次索取token的请求,通常带有如下参数:
很容易理解。
第六步:DataOwner验证用户授权码的真伪,向Requester响应令牌(token)
DataOwner收到请求,会验证一下用户授权码(code)的真伪,是不是由自己发出的。当验证成功,就可以响应了。token的响应通常是如下字段:
DataOwner角色注意,响应头中必须设置本响应不允许缓存。因为access_token通常是一次性的。被缓存会影响下次的请求。
第七步:Requester收到令牌,带上令牌向DataOwner请求用户数据
现在Requester收到了token了。已经证明了自身的纯洁,和用户的意愿。既然你来我往都自愿,那就可以大大方方地索取用户的数据了。
向DataOwner的用户数据路由请求就不是oauth2.0负责规范的范围了。但一定要带上刚刚获取的token吧?下面是个简单的例子:
第八步:DataOwner验证令牌,将Requester请求的用户信息响应过去
DataOwner验证自己发送的令牌真伪。如属真,则响应用户信息。
至于响应哪些用户信息,就通常是各家不同,看DataOwner角色提供的接入文档了。
第九步:Requester收到用户信息,执行登陆/注册操作
得到了用户的信息,这一步也没什么好说的。可以把用户信息存进自己的数据库注册用户。
(如目的不是第三方登陆,只是请求一部分资料,则可以拿资料接下来的事。)
第十步:Requester将该用户登陆/注册完毕,重定向User的页面,此时User发现自己已经登陆了。完毕
恭喜恭喜,用户终于看到页面动了,页面转到网站A,并且此时自己已经被注册为网站A的会员了。
终于达成了用户用网站B的信息来注册网站A的会员这一战略目的。
最后——感谢阮一峰大大!