给你的网站接入 github 提供的第三方登录
什么年代了还在用传统账号密码登录?没钱买手机号验证码组合?直接把鉴权和用户系统全盘托出依赖第三方(又不是不能用),省去鉴权系列 SQL
攻击、密码加密、CSRF
攻击、XSS
攻击,老板再也不用担心黑产盗号了(我们的系统根本没有号)
要实现上面的功能就得接入第三方登录,接下来就随着文章一起试试吧!
github
本章节将使用 github
作为第三方登录服务提供商
github
不愧是阿美力卡之光,极其简便的操作即可开启你的第三方登录之旅,经济又实惠,你可以通过快捷链接进入创建 OAuth
应用界面,也可以按照下面的顺序
然后填写相应的信息
生成你的密钥(Client secrets
),就可以去试试第三方登录了
组合 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
redirect_uri
默认是注册 OAuth
应用(Register a new OAuth application
)是填写的授权回调 URL
(Authorization callback URL
)
而对于 state
就在前端用随机字符串模拟,通常此类加密的敏感数据会再后端生成,而这里为了方便演示就采用了前端生成
详细参数请参考文档
鉴权验证
登录之后就可以进行相对应的验证,比如输入账号密码、授权、Github
客户端验证
成功鉴权后会再新弹出的页面重定向至 redirect_uri
注意要在属于用户操作的范畴下,比如点击按钮的操作,去使用 window.open(strUrl, strWindowName, [strWindowFeatures])
这种方式去跳转鉴权,否则像 window.open("https://github.com...", "_blank")
这种常见的写法,会报错
浏览器会以为是弹窗式广告,所以我推荐使用直接在当前窗口跳转的方法,而不是选择新开窗口或者浮动窗口
window.location.href = "https://github.com/login/oauth/authorize?client_id=b351931efd1203b2230e&redirect_uri=http://localhost:8080";
处理回调
通过用户授权时,Github
的响应如下
GET redirect_uri
参数
名称 | 类型 | 说明 |
---|---|---|
code | string | 鉴权通过的响应代码 |
state | string | 请求第三方登录时防 csrf 凭证 |
state
参数负责安全非常重要,想要快速通关的选手可以跳过这部分
对于这里的 state
处理可以分为前端处理和后端处理
前端处理
当 redirect_uri
是前端路由时,可以将之前提交的 state
从 localStorage
或者 sessionStorage
中取出,验证是否一致,再去向后端请求并带上 state
和 code
优点
无需缓存
state
缺点
需要防止
XSS
的DOM
型攻击
后端处理
当 redirect_uri
是后端时,后端需要持有 state
的缓存,具体做法可以在前端处理第三方登录时同步随机生成的 state
,并在后端缓存
优点
不需要防止
XSS
的DOM
型攻击
缺点
需要缓存
state
科普:早期 token
其实就是这里的 state
获取 token
第三方登录从本质上来讲就是获取到 token
,在安全的拿到 code
和 state
之后,需要向 github
发送获取 token
请求,其文档如下
POST https://github.com/login/oauth/access_token
参数
名称 | 类型 | 说明 |
---|---|---|
client_id | string | 必填。 从 GitHub 收到的 OAuth App 的客户端 ID。 |
client_secret | string | 必填。 从 GitHub 收到的 OAuth App 的客户端密码。 |
code | string | 必填。 收到的作为对步骤 1 的响应的代码。 |
redirect_uri | string | 用户获得授权后被发送到的应用程序中的 URL。 |
响应
名称 | 类型 | 说明 |
---|---|---|
access_token | string | github 的 token |
scope | string | 参考文档 |
token_type | string | token 类型 |
注意因为 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
总结
如果还没有了解过第三方登录的同学可以试试,毕竟不需要审核,有对应的 github
账号就行,截至写完文章的现在,我仍然没有通过微博第三方登录的审核/(ㄒoㄒ)/~~
参考资料
作者:2分钟速写快排
来源:juejin.cn/post/7181114761394782269