注册
web

给你的网站接入 github 提供的第三方登录

什么年代了还在用传统账号密码登录?没钱买手机号验证码组合?直接把鉴权和用户系统全盘托出依赖第三方(又不是不能用),省去鉴权系列 SQL 攻击、密码加密、CSRF 攻击、XSS 攻击,老板再也不用担心黑产盗号了(我们的系统根本没有号)

a04e08c5a3ee4bdab82c905490c16e91~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp

要实现上面的功能就得接入第三方登录,接下来就随着文章一起试试吧!

github

本章节将使用 github 作为第三方登录服务提供商

github 不愧是阿美力卡之光,极其简便的操作即可开启你的第三方登录之旅,经济又实惠,你可以通过快捷链接进入创建 OAuth 应用界面,也可以按照下面的顺序

616281c1a473461a9cf48d57092d6d59~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp?

然后填写相应的信息

76556818df5c487dbfe3b296e3ba6261~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp

生成你的密钥(Client secrets),就可以去试试第三方登录了

986924605639424db32c29433c2621ae~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp

组合 URL

您可以在线查看本章节源代码

这里我使用的是 express-generator 去生成项目,并且前后端分离,在选项上不需要 HTML 渲染器

npx express --no-view your-project-path && cd your-project-path

前端部分简单设置一下跳转验证

<html>
 <body>
   <div>
    第三方登录
     <br />
     <button onclick="handleGithubLoginClick()">github</button>
   </div>
 </body>
 <script>
   const handleGithubLoginClick = () => {
     const state = Math.floor(Math.random() * Math.pow(10, 8));
     localStorage.setItem("state", state);
     window.open(
       `https://github.com/login/oauth/authorize?client_id=b351931efd1203b2230e&redirect_uri=http://localhost:8080&state=${state}`,
       "_blank"
    );
  };
 </script>
</html>

其中有三个比较重要的 params

  1. client_id - string - “必需”。 注册时从 GitHub 收到的客户端 ID。

  2. redirect_uri - string - 用户获得授权后被发送到的应用程序中的 URL。 请参阅以下有关重定向 URL 的详细信息。

  3. state - string - 不可猜测的随机字符串。 它用于防止跨站请求伪造攻击。

redirect_uri 默认是注册 OAuth 应用(Register a new OAuth application)是填写的授权回调 URLAuthorization callback URL

而对于 state 就在前端用随机字符串模拟,通常此类加密的敏感数据会再后端生成,而这里为了方便演示就采用了前端生成

详细参数请参考文档

50ab773cad634bd3847b6aed681cfd1c~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp

鉴权验证

登录之后就可以进行相对应的验证,比如输入账号密码、授权、Github 客户端验证

c2c4708713fd483085df12ade0504ba5~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp?

成功鉴权后会再新弹出的页面重定向redirect_uri

e1a45e6fe67342788fb86e8fb022a471~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp

注意要在属于用户操作的范畴下,比如点击按钮的操作,去使用 window.open(strUrl, strWindowName, [strWindowFeatures]) 这种方式去跳转鉴权,否则像 window.open("https://github.com...", "_blank") 这种常见的写法,会报错

796eb92838b54d35b7e5598547002fb8~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp?

浏览器会以为是弹窗式广告,所以我推荐使用直接在当前窗口跳转的方法,而不是选择新开窗口或者浮动窗口

window.location.href = "https://github.com/login/oauth/authorize?client_id=b351931efd1203b2230e&redirect_uri=http://localhost:8080";

处理回调

通过用户授权时,Github 的响应如下

GET redirect_uri

参数

名称类型说明
codestring鉴权通过的响应代码
statestring请求第三方登录时防 csrf 凭证

state 参数负责安全非常重要,想要快速通关的选手可以跳过这部分

对于这里的 state 处理可以分为前端处理和后端处理

前端处理

redirect_uri 是前端路由时,可以将之前提交的 statelocalStorage 或者 sessionStorage 中取出,验证是否一致,再去向后端请求并带上 statecode

优点

  1. 无需缓存 state

缺点

  1. 需要防止 XSSDOM 型攻击

后端处理

redirect_uri 是后端时,后端需要持有 state 的缓存,具体做法可以在前端处理第三方登录时同步随机生成的 state,并在后端缓存

优点

  1. 不需要防止 XSSDOM 型攻击

缺点

  1. 需要缓存 state

科普:早期 token 其实就是这里的 state

获取 token

第三方登录从本质上来讲就是获取到 token,在安全的拿到 codestate 之后,需要向 github 发送获取 token 请求,其文档如下

POST https://github.com/login/oauth/access_token

参数

名称类型说明
client_idstring必填。 从 GitHub 收到的 OAuth App 的客户端 ID。
client_secretstring必填。 从 GitHub 收到的 OAuth App 的客户端密码。
codestring必填。 收到的作为对步骤 1 的响应的代码。
redirect_uristring用户获得授权后被发送到的应用程序中的 URL。

响应

名称类型说明
access_tokenstringgithubtoken
scopestring参考文档
token_typestringtoken 类型

注意因为 client_secret 属于私钥,所以该请求必须放在后端,不能在前端请求!否则会失去登录的意义

const { default: axios } = require("axios");
const express = require("express");
const router = express.Router();

router.post("/redirect", function (req, res, next) {
 const { code } = req.body;
 axios({
   method: "POST",
   url: "https://github.com/login/oauth/access_token",
   headers: {
     "Accept": "application/json",
  },
   timeout: 60 * 1000,
   data: {
     client_id: "your_client_id",
     client_secret: "your_client_secret",
     code,
  },
})
  .then((response) => {
     res.send(response.data);
  })
  .catch((e) => {
     res.status(404);
  });
});

module.exports = router;

注意,由于 github 的服务器在国外,所以这个请求非常容易超时或者失效,建议做好对应的处理(或者设置一个比较长的时间)

最后拿到对应的 token

8b724e369bc741be9e8ab3b8046d086c~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp

总结

如果还没有了解过第三方登录的同学可以试试,毕竟不需要审核,有对应的 github 账号就行,截至写完文章的现在,我仍然没有通过微博第三方登录的审核/(ㄒoㄒ)/~~

参考资料

  1. 授权 OAuth 应用 - Github Docs

  2. 给你的网站添加第三方登录以及短信验证功能

作者:2分钟速写快排
来源:juejin.cn/post/7181114761394782269

0 个评论

要回复文章请先登录注册