Gist网站实现(1)-通过第三方登陆GitHub

安装 Express

1
npm install -g express-generator

新建 Express 项目初始化

1
npx express-generator --view=pug nodegist

安装依赖包并检查

1
2
3
cd nodegist
npm i yarn -g
yarn start

安装依赖包并检查

安装 nodemon 工具,使其监控文件变动,自己重启服务。

yarn add nodemon –dev

修改 package.json,将 script 下的 start 命令的 node 换为 nodemon。下次使用 yarn start 时即可通过 nodemon 启动

nodemon

通过第三方登入 github

直接登陆 github

用户在 github 登陆,输入用户名密码,传入 github,github 查询对应数据库,确认无误后,通过 session 标识用户登陆成功

第三方登陆

第三方不可信,故不直接使用用户名和密码进行登陆,而是采用限制性的登入授权解决。=>OAuth

下图源自 easy 老师方糖全站课堂:

github

核心步骤为:获取 Code,用 Code 换 AccessToken

添加登陆页面

页面由路由、回调函数、模板三部分组成

1、在 routes/users.js 添加路由规则

1
2
3
router.get('/login',function(res,res,next){
res.render('login');
});

2、新建 views/login.jade 作为模板

1
2
3
4
5
extends layout
block content
h1 login
p
a(href='#') Login with Github

jade 是 Express 默认模板引擎,现已改名为 pug,其采用缩进来区分层级。
每一层将标签名写在最前面,然后用括号写属性,最后是标签对应的文字内容。
html2jade.org 可在线把 HTML 转化为 jade 语法
开头的extends layout即以 layout.jade 为基础,进行 block 替换

创建 OAuth App

1

2

3

拼接请求链接(Github 的 OAuth 文档)

  1. 定义 Client 相关信息为常量

5

  1. 拼接 GET 参数,使用 encodeURIComponent 进行编码,保证参数中有特殊字符时不会报错

6

  1. 将 url 作为参数传给模板

7

  1. 在模板 views/login.jade 将 a 标签的 href 换为 url

8

  1. 打开 login 页面即可看到授权页面

9

10

创建授权页面后回调函数

  1. 点击授权按钮后,code 会出现在回调 URL 上

11

  1. 安装必要的库
1
yarn add axios url-search-params-polyfill querystring
  1. 在 users.js 引入新安装的库

NodeJS 特性

当我们通过 require 载入 module.exports 导出的内容时,如果是对象, NodeJS 会自动缓存它。如果是函数,则不会被缓存。

1
2
3
4
5
6
//构成表单数据
require('url-search-params-polyfill');
//发起HTTP请求
const axios = require('axios');
//分析URL里的参数
const querystring = require('querystring');
  1. 新增 callback 路由规则,实现回调函数

检查 url 中是否有 code,没有则报错

  1. 获取到 code 后需要再次发送请求获取 accessToken,此时根据文档需要发送 POST,故无法通过拼接 URL 实现

通过 axios 库发起请求,axios 支持 await 语法,其 post 方法接受两个参数,url 和要发送的数据

通过 URLSearchParams 按格式拼接要发送的数据

通过 url-search-params-polyfill 兼容低版本环境

  1. 使用 querystring.parse 从 URL 中提取出 access_token,则即可使用 access 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
 //req,res为Express传递的两个参数,分别为request请求和response响应
router.get("/ghcallback", async (req, res) => {
if (!req.query.code) res.status(500).send("bad code!");
console.log("in callback");
console.log(req.query.code);

//拼接POST请求参数
let params = new URLSearchParams();
params.append("client_id", GH_CLIENT_ID);
params.append("client_secret", GH_CLIENT_SECRET);
params.append("code", req.query.code);
params.append("redirect_url", GH_CALLBACK);

//发起请求
const { data } = await axios.post(
"https://github.com/login/oauth/access_token",
params
);

//使用querystring提取access_token的值
if (data) {
const acode = querystring.parse(data).access_token;
//使用access_token调用Github接口查询当前用户的信息
const user = await axios.get(
"https://api.github.com/user?access_token=" + acode
);
console.log("Got user info:", user.data);

res.json(user.data);
res.end();
}
});

info

  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2020-2024 Aweso Lynn
  • PV: UV: