推荐 原创 视频 Java开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发
Lambda在线 > 开发者实验手册 > 从0开始设计Oauth2.0 - 授权码模式

从0开始设计Oauth2.0 - 授权码模式

开发者实验手册 2018-10-21

摘要:当我们在网站上点击“使用qq登陆”/“微信登陆”发生了什么事情?如果我的网站也想使用第三方账号登陆,要怎样接入他们,接入的流程是怎样设计的?下面我们一起来探讨。

Oauth2.0的应用场景?

读者您好,假设您现在是公司的技术负责人,公司拥有用户的账户信息(头像,昵称等),拥有用户的相册信息,拥有用户的消费记录信息等。为了提升公司的影响力,您希望其他的一些公司也能利用这些信息。当然,这些数据都是用户的隐私数据,公司不能私下将数据发送给第三方,得先获得用户的授权。在设计授权策略的时候,您大概率会考虑到Oauth。Oauth 就是用于解决上述问题的一套标准协议,但这里暂不细说 Oauth 的内容,而先尝试探索其实现思路。

交互流程

于用户而言,授权流程应该是怎样的操作?

首先用户访问的是第三方网站,然后授权第三方网站获取授权资源,所以第三方网站先要设置授权入口。当用户点击授权按钮后,用户需要证明自己是“自己”,也就是需要用户登录自己的账号。登录过程中,第三方网站会告诉用户其申请了什么样的资源。最后,用户点击授权即完成这次授权。

以在知乎使用 QQ 登录为例:

在网站有授权入口,用户点击开始授权:

点击QQ的图标后打开了 QQ 的授权页面,输入 QQ 账号密码,过程中提示知乎网申请了 QQ 昵称、头像和性别信息:

从0开始设计Oauth2.0 - 授权码模式

点击【授权并登录】完成了授权,知乎网获得了用户的 qq 昵称、头像和性别信息。

知乎网进入克绑定手机的流程,这部分就和授权协议无关了。有些网站直接完成登录,有些需要绑定手机,有些需要填写身份信息,不同的网站会根据自身的业务而不同。

从0开始设计Oauth2.0 - 授权码模式

设计思路

命名

在思路设计之前,先明确几个定义:

    - 像qq这样的资源拥有者下文称为“授权方”。

    - 像知乎这样的第三方应用下文称为“网站应用”。

    - qq的拥有者称为“授权用户”。

    - 授权用户授权给第三方应用的信息称为“授权资源”。(昵称,头像等就是授权资源

    - 上面图二,授权用户输入账号密码的页面称为“授权页面”。

    - 下面还会提到“申请接入”的概念,具体下述。

思路

上面提到,使用qq登录的时候,知乎网会获得用户的昵称头像性别信息。除了这些信息,腾讯还开放了其他一些信息:

即设计授权流程的第一步就是设计一套 API ,规定第三方公司能访问什么资源,不能访问什么资源。

网站应用在获取授权信息前,授权方还需要对其进行资质审核。比如需要网站应用提供网站域名,网站用途等,然后审核的时候验证网站是否备案,网站用途是否和备案信息一致等。

以腾讯为例,腾讯设计了 https://connect.qq.com/ 开放平台,审核通过后,平台提供 appid (用于作为第三方应用的唯一标志)和 appkey(用途后面说明)。在开放平台填写申请的过程称为“申请接入”。

网站应用在请求授权资源的时候,需要打开授权页面,授权用户将在授权页面上完成授权操作。网站应用可以通过 <a> 标签直接跳转到授权页面,也可以通过 iframe 来嵌入,本质是向授权方发送一个 GET 请求。

GET 请求的参数该如何设计?

首先,当然要告知授权方当前的网站应用是“谁”?这个可以通过上面提到的 appid 来实现。在 GET 请求中,还要告知授权方授权资源是哪些。所以,现在构造的请求链接是:

https://graph.qq.com/oauth2.0/authorize?
client_id=${appid}&scope=${scope}

其中,

client_id 表示 appid,

scope 表示需要获取的授权资源,如申请用户信息的时候值为 get_user_info,申请相册信息的时候值为 list_album 等

那授权方要怎样将授权资源返回给网站应用?

直接在上面的 GET 请求中返回授权资源显然是不合理的,因为 appid 和 scope 可以轻而易举地在网站中获取,意味着可以轻而易举地伪造这个请求,授权资源会因此而泄漏。

为解决上述问题,可以将一个授权码返回给网站应用,然后网站应用再通过授权码来获取信息。由于网站应用是通过 <a> 标签或者通过 iframe 来打开授权页面的,当前页面属于资源方,所以授权完毕后不能直接返回数据,而是要将数据返回给授权网站。通过重定向并在重定向的 url 里带上要返回的参数可以实现这步操作。而重定向的路径在打开授权页面的时候就需要告诉授权方。所以,构造的链接就是:

https://graph.qq.com/oauth2.0/authorize?
client_id=${appid}&scope=${scope}&redirect_uri=${redirect_uri}

在授权完成后,浏览器会进行重定向,而重定向的 url 如下:

redirect_uri?code=${code}
http://www.example.com/oauth/callback?code=${code}

code 就是授权码。

在网站应用的服务器后台需要有处理 /oauth/callback 这个路由的方法。本质上,网站应用的服务器只需要将 code 发送给资源方即可。

那么资源方先要确保 code 是来自网站应用的服务器。当然可以在申请接入的时候就填写网站应用的IP列为白名单,但是这样对于网站应用来说太不灵活了。

上面提到申请接入完毕后,会获得 appid 和 appkey。这两个就相当于网站应用的账号和密码,资源方通过账号密码就可以鉴别应用服务器。

网站应用将 appid, appkey, code 发送给授权方后,授权方通过 appid 和 appkey 检测网站应用的身份是否合法,然后再通过 code 来判断授权是否合法。检查成功后,授权方不会直接返回授权资源,而是返回三个参数:能够访问授权资源的令牌 accesstoken,accesstoken的过期时间expiresin 和用于更新 accesstoken 的更新令牌refresh_token。

这样能够避免用户频繁授权,提升用户体验。用户只需要授权一次,网站应用获得了访问令牌并缓存下来,以后只需要利用访问令牌就可以访问授权资源。从安全的角度考虑,给accesstoken 设置有效时间,通过 refreshtoken 来更新令牌。

最后,网站应用通过 access_token 获取了授权资源,完成了整个流程。

上面提到的过程,就是 Oauth2.0 的授权码模式的原理。目前 qq,微信,是微博等都使用这个模式来开放资源。真正的实现方式所传递的参数和上述举例的会有些许不同,接入不同的授权方也会有所不同,比如请求 code 的时候,还需要带上 response_type 参数和 state 参数,具体的细节不做详述。

最后


版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《从0开始设计Oauth2.0 - 授权码模式》的版权归原作者「开发者实验手册」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注开发者实验手册微信公众号

开发者实验手册微信公众号:gh_7e067ada74ec

开发者实验手册

手机扫描上方二维码即可关注开发者实验手册微信公众号

开发者实验手册最新文章

精品公众号随机推荐