需求来源于我以前在做个人微博时候的一个产品问题,就是用户不可能为了评论一篇文章而去这么麻烦的注册登录,这个步骤通过第三方授权登录完全可以很好的解决,那么我们有几个选择
题外话:微信公众号没有进行企业认证的个人公众号虽然做不了授权但是仍然可以自己关注自己公众号后利用自己的openId做一个发送的动作来做提醒功能,但是没有客户接口无法很好的直接调用回复接口来回复,所以当用户评论你的文章后,可能我们可以发送一个提醒,但是却无法回复,后续个人再研究下,能不能有其他替代方案使我们在手机上能接收提醒并实时回复吧~下面正式进入教程
首先我们必须登录上 github 申请一个 app,步骤如下
下面进行代码分析阶段,先将授权的步骤及我代码的思路告诉大家
最终我们以拿到用户信息及Id为成功的依据,我们需要进行3次请求,与微信授权的复杂程度一样,不过 github 方便在不用像微信一样拼接 XML 字符串了
在这个过程中我为了方便,直接用了 ejs 作为模板引擎并将需要的用户信息存入了 session 中来保证用户不用频繁的二次登陆,在授权成功并拿到用户信息后回到根目录,由于是简单的 demo ,故没有做成 MVC 的分层结构。
后端
var path = require('path')
var qs = require('querystring')
var express = require('express');
var session = require('express-session');
var request = require('request');
var app = express();
// 设置模板目录
app.set('views', path.join(__dirname, 'view'));
// 设置模板引擎为 ejs
app.set('view engine', 'ejs');
app.use(express.static('static'));
// session 中间件
app.use(session({
secret: 'test', // 通过设置 secret 来计算 hash 值并放在 cookie 中,使产生的 signedCookie 防篡改
resave: true, // 强制更新 session
saveUninitialized: false, // 设置为 false,强制创建一个 session,即使用户未登录
}));
// 设置模板全局常量
app.locals.page = {
title: 'github 接口测试',
description: '学习测试'
};
// 添加模板必需的三个变量
app.use(function (req, res, next) {
res.locals.user = req.session.user
next();
});
// code => token => userInfo 的过程
function getUserInfo (code) {
return new Promise((resolve, reject) => {
request.get({
url: `https://github.com/login/oauth/access_token?client_id=${client_id}&client_secret=${client_secret}&code=${code}`,
}, (err, res, body) => {
token = qs.parse(body).access_token
resolve(token)
})
}).then((token) => {
console.log(token)
return new Promise((resolve, reject) => {
request.get({
url: `https://api.github.com/user?access_token=${token}`,
headers: {
'User-Agent': 'Awesome-Octocat-App'
}
}, (err, res, body) => {
resolve(JSON.parse(body))
})
})
})
}
// 你申请 github 应用的 ID(your github app's Client ID)
var client_id = 'XXXXXXXXX'
// 你申请 github 应用的 secret(your github app's Client Secret)
var client_secret = 'XXXXXXXXXX'
var token = ''
app.get('/', (req, res) => {
res.render('index');
})
app.get('/login', (req, res) => {
res.redirect(`https://github.com/login/oauth/authorize?client_id=${client_id}`)
})
// 你申请 github 应用的授权回调地址(Authorization callback URL)
app.get('/github/oauth', (req, res) => {
getUserInfo(req.query.code).then((userInfo) => {
// 将用户信息存入 session 并重定向回首页
req.session.user = {
name: userInfo.login,
avatar: userInfo.avatar_url,
user_id: userInfo.id
}
res.redirect('/')
})
})
// 创建你申请 github 应用的主页 URL 服务(Homepage URL)
var server = app.listen(3000, (req, res) => {
let address = server.address();
console.log(`服务已启动,端口号为: ${address.port}`);
})
前端 ejs 首页模板
<html>
<head>
<meta charset="utf-8">
<title><%= page.title %>title>
<style media="screen">
html,body {
margin: 0 0;
padding: 0 0;
}
style>
head>
<body>
<div class="">
<a href="/login">授权github登录a>
div>
<% if (user) {%>
<p><%= user.name %>p>
<img src="<%= user.avatar %>" alt="">
<% } %>
body>
html>
所有代码我都会放入这里,package.json 中多余的依赖大家无视掉就好,因为这是我的一个测试项目demo的公共包~
https://github.com/YOLO0927/github-OAuth-demo