概述

在开发一个登录认证功能的时候,我们以前可能会想自己搞一套,一般情况就是用户名(邮箱)加密码的方式,这种方式的话,比较麻烦,经常会忘记用户名或者密码,而且需要记住两个字符串,所以用户体验非常不友好;然后到了后面 APP 时代可能就是直接输入手机号就行了,然后短信收验证码,这种方式虽然挺友好,但是还是不够,毕竟中间还有一个输入手机号,然后等待验证码的过程,还得输入验证码,当然,在 Android 很早的时候以及最近的 IOS 中,都提供了自动提取验证码的功能,但是,体验还不够好;当微信、微博和淘宝的 APP 体系已经达到一定程度的时候,现在很多 APP 都提供一键登录的功能了,效果就是在登录页面我都不用输入什么信息了,只需要点击一下对应的图标,然后跳转到对应的 APP 上授权一下,就可以直接使用 APP 了,这个体验极大得提升了方便度,而我今天要聊的就是如果在网站中通过 OAuth2 对接 Github 实现类似的效果,直接点击一个图标就可以在网站上让用户达到登录过的状态。

根据维基的介绍:

开放授权(OAuth)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。

其实这里的效果并不是说我们就直接在我的网站上注册了一个账号,然后对应到 Github 上的账号,对于 OAuth 来说,只是我们网站可以通过用户的授权,拿到用户再 Github 上的账号信息,只是我们的实现方式是将拿到的这些用户信息在我们的网站上创建一个账号,这样,我们的网站就可以独立的保存一些用户的定制化配置。

Github OAuth

对于 Github 来说,可以提供给第三方的信息非常多,但是,基于最少原则,我只使用到我需要的最少信息,所以我只会获取用户的用户名和邮箱这两个信息,邮箱可以用来唯一标示用户,而用户名可以用来友好化展示用户信息,而不用用户再主动修改一遍,为了实现这个目标,我们需要先来看一下 Github OAuth2 的对接流程:

可以看到这整个流程还是比较复杂,期间会有2-3 个的 302 重定向操作,但是大部分工作都是客户端做的,这里有几个关键点需要说一下,分别是:

这里有个问题,为什么要搞得这么麻烦,为什么不直接 Github 就返回一个 Token 给用户,用户就拿着这个 Token 请访问网站不就好啦?那么考虑这么一个场景,假设用户的网络不是安全的,这个 token 被别人截获了,那么这个截获 token 的人是不是就可以拿着这个 token 去 Github 访问用户的信息了?而通过 code,这个 code 是需要网站的服务器通过自己的应用标识和应用密码加密之后再去 Github 获取,并且返回给客户端,那么对于 Github 来说,即使你的网络不安全,问题也不会出现在我这部分,我的数据也不会泄露,只会在网站对于自己的用户机制不完善的情况下泄露网站自己的用户信息。

实现

ok,说完流程之后,就看一下要怎么实现这个代码,因为我用的是 Python,所以下面的流程是以 Python 编程语言为例进行介绍的:

  1. 第一步肯定是得在 Github 上创建一个你的应用,创建应用的地址是:创建应用
  2. 通过 authlib 编写你的服务端
  3. 从 cookie 中获取用户的信息进行认证

下面我给出一个 python 的代码实现,因为 Authlib 这个库已经内置的 Flask 的支持,所以让 Flask 的实现变得尤为简单,这里是他的 Sample 实现,你只需要修改一下自己的 GITLAB_CLIENT_IDGITLAB_CLIENT_SECRET 即可:

集成之后,然后访问地址:http://your-domain/github/login 即可跳转到 Github 授权页,然后点击授权之后就会返回到用户的信息页,你会在这个页面就可以看到你授权 Github 给自己网站的用户权限了。

Reference