在网页中接入 GitHub 帐号登录

陪她去流浪 桃子 2019年07月27日 编辑 阅读次数:4457

上一篇文章中,我简要地介绍了在网页中接入Google登录的方式,今天这篇文章再介绍一下接入GitHub登录的方式。同样是由于项目需要,所以学习了一番。 和 Google 相同的是,GitHub也是采用 OAuth 的方式授权。而不同点在于,Google 签发 JWT Token,而 GitHub 则是标准的 OAuth 认证过程。

OAuth 授权原理步骤

  • 网站携带 ClientID 跳转到 GitHub 授权页面
  • 用户授权后,GitHub 携带授权码重定向回到网站回调页面
  • 网站通过授权码向 GitHub 请求用户令牌(Token)(验证授权码合法性)
  • 网站通过用户令牌请求用户信息(或其它接口)

创建一个 OAuth App

OAuth 在 GitHub 中被叫作 OAuth Apps,所以需要先创建一个 OAuth App。

通过点击右上角头像的 SettingsDeveloper settingsOAuth Apps 进入到 OAuth Apps 创建和管理页面:https://github.com/settings/developers

如下图所示,我已经创建了两个。第二个是用于我博客登录的。

oauth-apps

点击右上角的“New OAuth App”进入新的 OAuth App 创建页面,需要填写的信息非常少。

题外话:GitHub 的页面风格看着比 Google 的真是要舒适多了。

new-oauth-app

注意最后一个回调地址(前/后端均可,取决你的实现),当用户点击授权后,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 请不要泄露。

oauth-app-page

前端添加GitHub登录代码

在自己网站的登录页面,加上一个GitHub登录的按钮,点击这个按钮后,跳转到GitHub授权页面供用户授权。 以下代码来自我博客和简单实现,仅供参考。

GitHub授权页面:https://github.com/login/oauth/authorize?client_id=你的ClientID

1
2
3
4
5
6
7
8
9
<!-- 图片来自GitHub主页左上角的SVG -->
<svg id="github" height="32" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>

<script>
    var github = document.getElementById('github');
    github.addEventListener('click', function() {
        location.href = "https://github.com/login/oauth/authorize?client_id=你的ClientID";
    });
</script>

在点击上面的图片按钮后,页面会转到GitHub授权页面:

授权中

点击绿色的授权按钮后,用户就会被重定向到注册 OAuth App 时的回调地址,参数中携带授权码code

后端通过授权码向GitHub请求用户令牌(Token)

前一篇文章在讲到后端处理 Google 的 JWT Token 的时候,后端会向 Google 验证拿到的 JWT 是否合法。在我们拿到 GitHub 的授权码的时候,同样需要向 GitHub 验证这个授权码是否合法,这个过程即是请求令牌的过程。

请求用户令牌(access_token)

令牌请求地址:POST https://github.com/login/oauth/access_token

参数详见:https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/#2-users-are-redirected-back-to-your-site-by-github

注意:这虽然是个 POST 请求,但是请求的参数是放在 URL 中的,不在 BODY 中。

有 3 个参数是必选的:

名字 含义
client_id 你的 ClientID
client_secret Client Secret
code 授权码

成功请求后,GitHub 会返回用户令牌(格式可以通过参数自定义,详见参数说明):

1
{"access_token":"e72e16c7e42f292c6912e7710c838347ae178b4a", "scope":"repo,gist", "token_type":"bearer"}

用令牌调用GitHub接口获取用户信息

拿到用户的令牌后,就可以做很多事了,今天我这篇文章只讲解获取用户信息。

用户信息接口地址:GET https://api.github.com/user

在发请求时,需要携带用户令牌,这个令牌放在 HTTP 请求头部字段 Authorization 中。 虽然GitHub返回的是Bearer Token类型,但是API接口的要求的名字却是token,见下。

1
2
3
GET https://api.github.com/user

Authorization: token 用户令牌

返回的信息如下:

 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
{
  "login": "movsb",
  "id": 5374525,
  "node_id": "MDQ6VXNlcjUzNzQ1MjU=",
  "avatar_url": "https://avatars1.githubusercontent.com/u/5374525?v=4",
  "gravatar_id": "",
  "url": "https://api.github.com/users/movsb",
  "html_url": "https://github.com/movsb",
  "followers_url": "https://api.github.com/users/movsb/followers",
  "following_url": "https://api.github.com/users/movsb/following{/other_user}",
  "gists_url": "https://api.github.com/users/movsb/gists{/gist_id}",
  "starred_url": "https://api.github.com/users/movsb/starred{/owner}{/repo}",
  "subscriptions_url": "https://api.github.com/users/movsb/subscriptions",
  "organizations_url": "https://api.github.com/users/movsb/orgs",
  "repos_url": "https://api.github.com/users/movsb/repos",
  "events_url": "https://api.github.com/users/movsb/events{/privacy}",
  "received_events_url": "https://api.github.com/users/movsb/received_events",
  "type": "User",
  "site_admin": false,
  "name": "桃子",
  "company": "Shopee",
  "blog": "https://blog.twofei.com",
  "location": "Shenzhen, China",
  "email": null,
  "hireable": null,
  "bio": null,
  "public_repos": 46,
  "public_gists": 1,
  "followers": 108,
  "following": 11,
  "created_at": "2013-09-03T16:09:34Z",
  "updated_at": "2019-07-21T13:32:02Z"
}

GitHub的登录名(login)是可变的,用户ID(id)不变。所以:如果这个ID没有与我们自己的用户系统绑定用户,则创建一个新用户绑定。否则,直接创建此用户的会话即可。

参考资料

标签:github · 登录