在网页中接入 GitHub 帐号登录
在上一篇文章中,我简要地介绍了在网页中接入Google登录的方式,今天这篇文章再介绍一下接入GitHub登录的方式。同样是由于项目需要,所以学习了一番。 和 Google 相同的是,GitHub也是采用 OAuth 的方式授权。而不同点在于,Google 签发 JWT Token,而 GitHub 则是标准的 OAuth 认证过程。
OAuth 授权原理步骤
- 网站携带 ClientID 跳转到 GitHub 授权页面
- 用户授权后,GitHub 携带授权码重定向回到网站回调页面
- 网站通过授权码向 GitHub 请求用户令牌(Token)(验证授权码合法性)
- 网站通过用户令牌请求用户信息(或其它接口)
创建一个 OAuth App
OAuth 在 GitHub 中被叫作 OAuth Apps,所以需要先创建一个 OAuth App。
通过点击右上角头像的 Settings → Developer settings → OAuth Apps 进入到 OAuth Apps 创建和管理页面:https://github.com/settings/developers。
如下图所示,我已经创建了两个。第二个是用于我博客登录的。
点击右上角的“New OAuth App”进入新的 OAuth App 创建页面,需要填写的信息非常少。
题外话:GitHub 的页面风格看着比 Google 的真是要舒适多了。
注意最后一个回调地址(前/后端均可,取决你的实现),当用户点击授权后,GitHub 会携带**授权码(code)**回调/重定向到这个地址。
这个地址可以是任意合法的地址,比如http://localhost:8080/
,在本地开发调试的使用。
回调时,GitHub 会追加一个名为code
的查询参数到刚刚指定的回调地址中。(这个名为code
的参数是hardcode的,没有找到地方可以修改)比如:https://blog.twofei.com/login?type=github&code=xxxxxx
,注意后面的 code 部分。
另外,由于这是一个追加到 URL 中的查询参数,而且很明显是通过浏览器重定向回调的,所以这是一个 GET 请求,不是 POST。 我的博客最开始只支持 POST 登录,后来为了支持 GitHub,增加了 GET 方式登录。
由于 code 是通过 URL 传输的,为了更加安全起见:建议网站支持 HTTPS。(现在有完全免费的证书了,谁还不上 HTTPS 呢?)
创建好后,就可以拿到 Client ID 和对应的 Client Secret,同时还可以设置一个头像。Client ID 可以公开,Client Secret 请不要泄露。
前端添加GitHub登录代码
在自己网站的登录页面,加上一个GitHub登录的按钮,点击这个按钮后,跳转到GitHub授权页面供用户授权。 以下代码来自我博客和简单实现,仅供参考。
GitHub授权页面:https://github.com/login/oauth/authorize?client_id=你的ClientID。
1 2 3 4 5 6 7 8 9 |
|
在点击上面的图片按钮后,页面会转到GitHub授权页面:
点击绿色的授权按钮后,用户就会被重定向到注册 OAuth App 时的回调地址,参数中携带授权码code
。
后端通过授权码向GitHub请求用户令牌(Token)
前一篇文章在讲到后端处理 Google 的 JWT Token 的时候,后端会向 Google 验证拿到的 JWT 是否合法。在我们拿到 GitHub 的授权码的时候,同样需要向 GitHub 验证这个授权码是否合法,这个过程即是请求令牌的过程。
请求用户令牌(access_token)
令牌请求地址:POST https://github.com/login/oauth/access_token。
注意:这虽然是个 POST 请求,但是请求的参数是放在 URL 中的,不在 BODY 中。
有 3 个参数是必选的:
名字 | 含义 |
---|---|
client_id | 你的 ClientID |
client_secret | Client Secret |
code | 授权码 |
成功请求后,GitHub 会返回用户令牌(格式可以通过参数自定义,详见参数说明):
1
|
|
用令牌调用GitHub接口获取用户信息
拿到用户的令牌后,就可以做很多事了,今天我这篇文章只讲解获取用户信息。
用户信息接口地址:GET https://api.github.com/user。
在发请求时,需要携带用户令牌,这个令牌放在 HTTP 请求头部字段 Authorization
中。
虽然GitHub返回的是Bearer Token类型,但是API接口的要求的名字却是token
,见下。
1 2 3 |
|
返回的信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
GitHub的登录名(login)是可变的,用户ID(id)不变。所以:如果这个ID没有与我们自己的用户系统绑定用户,则创建一个新用户绑定。否则,直接创建此用户的会话即可。