如何进行 github 的第三方授权(附 nodeJs demo)

需求来源于我以前在做个人微博时候的一个产品问题,就是用户不可能为了评论一篇文章而去这么麻烦的注册登录,这个步骤通过第三方授权登录完全可以很好的解决,那么我们有几个选择

  • 腾讯系-微信登录 (需要企业登记的服务号才能进行第三方的网页授权~放弃)
  • github-oAuth app登录(可行,并且开放了评论与创建话题等接口,唯一弊端就是非技术人员可能不会有github账号,这种情况的替代方案目前个人为匿名评论来解决)
  • 其他方案我再研究研究

题外话:微信公众号没有进行企业认证的个人公众号虽然做不了授权但是仍然可以自己关注自己公众号后利用自己的openId做一个发送的动作来做提醒功能,但是没有客户接口无法很好的直接调用回复接口来回复,所以当用户评论你的文章后,可能我们可以发送一个提醒,但是却无法回复,后续个人再研究下,能不能有其他替代方案使我们在手机上能接收提醒并实时回复吧~下面正式进入教程

首先我们必须登录上 github 申请一个 app,步骤如下

  1. 登录 github
  2. 点击头像下的 Settings -> Developer settings 右侧 New OAuth App
  3. 填写申请 app 的相关配置,重点配置项有2个
    1. Homepage URL 这是后续需要使用授权的 URL ,你可以理解为就是你的项目根目录地址
    2. Authorization callback URL 授权成功后的回调地址,这个至关重要,这是拿到授权 code 时给你的回调地址

附上图示
配置图示

下面进行代码分析阶段,先将授权的步骤及我代码的思路告诉大家

最终我们以拿到用户信息及Id为成功的依据,我们需要进行3次请求,与微信授权的复杂程度一样,不过 github 方便在不用像微信一样拼接 XML 字符串了

  1. 先拿到请求 token 的 code,这个会在授权成功后回调地址的 get 参数上给你;
  2. 用拿到的 code 去请求 token;
  3. 用 token 去请求用户的个人信息;

在这个过程中我为了方便,直接用了 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 首页模板

<!DOCTYPE html>
<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

猜你喜欢

转载自blog.csdn.net/yolo0927/article/details/79315824