第三方登入例子-GitHub授权登入(node-koa)

内存泄漏者
• 阅读 9649

前言

第三方登入太常见了,微信,微博,QQ...总有一个你用过。当然看这篇文章的你,应该还用过github登入。这篇分享是在上一篇基于node的登入例子(node-koa-mongoose)的基础增加了github账号第三方授权登入功能,如果有些代码,这篇中美介绍,你可以先去看下上一篇的分享。

本项目源码地址https://github.com/linwalker/...

第三方登入

第三方登入主要基于OAuth 2.0。OAuth协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH是安全的 ---- 百度百科

更详细的介绍可以看这篇文章理解OAuth 2.0

github 授权登入

原理过程

先来大致了解下第三方通过GitHub账号授权登入的过程,具体实现结合后面代码讲解

  • 1.获取code

    第三方客户端向`https://github.com/login/oauth/authorize`发送get请求,带上`?client_id=XXXXXX`参数,这时会跳转到GitHub登入页面,授权后GitHub会向客户端返回`https://redirect_url?code=XXXXXX`。其中`client_id`和`redirect_url`是第三方事先在GitHub平台上配置好的。
    
  • 2.通过code获取access_token

    客户端处理`https://redirect_url?code=XXXXXX`请求,获取code值,向`https://github.com/login/oauth/access_token`发起post请求,请求参数为`client_di`,`client_secret`和`code`。
    
  • 3.通过access_token获取用户GitHub账号信息

第二步的请求会返回这样access_token=d0686dc49a22d64e77402db072b719f510f22421&scope=user&token_type=bearer的内容,拿到access_token只需要向https://api.github.com/user?access_token=xxx发送GET请求,即可获取到登录用户的基本信息,

具体实现

GitHub注册应用

首先你要有一个GitHub账号,然后进入settings -> OAuth application -> Register a new application。进来后你会看到下面这个页面:

第三方登入例子-GitHub授权登入(node-koa)

依次填好应用名称,应用地址和授权回掉地址后点击Register application按钮,会生成一个client Idclient Secret,用于后面向GitHub发送请求传参。

第三方登入例子-GitHub授权登入(node-koa)

Github授权请求(获取code)

在页面中添加GitHub登入跳转按钮,并在路由中对跳转请求进行转发处理:

//在node-login/components/LoginTab.js

<a href="/github/login">
     <Icon type="github" style={{fontSize: 20, color: '#000'}}/>
</a>

第三方登入例子-GitHub授权登入(node-koa)

添加跳转按钮后,增加相应路由处理,路由入口中添加/github路径处理

//在node-login/routes/index.js

const github = require('./github');
router.use('/github', github.routes(), github.allowedMethods());

最后是具体的路由处理

//在node-login/routes/github.js
const config = require('../config');
const router = require('koa-router')();
const fetch = require('node-fetch');
const routers = router
    .get('/login', async (ctx) => {
        var dataStr = (new Date()).valueOf();
        //重定向到认证接口,并配置参数
        var path = "https://github.com/login/oauth/authorize";
        path += '?client_id=' + config.client_id;
        path += '&scope=' + config.scope;
        path += '&state=' + dataStr;
        //转发到授权服务器
        ctx.redirect(path);
    })
module.exports = routers;

在config中事先添加配置请求所需参数client_idclient_secretscope

module.exports = {
    'database': 'mongodb://localhost:27017/node-login',
    'client_id': '83b21756e93d6ce27075',
    'client_secret': 'd87c4163ece5695a9ded1e8bf2701c5ee2651f28',
    'scope': ['user'],
};

其中scope参数可选。就是你期待你的应用需要调用Github哪些信息,可以填写多个,以逗号分割,比如:scope=user,public_repo。state参数非必需,用于防治跨域伪造请求攻击。

现在可以运行一下项目,点击小黑猫,跳转到授权登入页面(没登入过,要输入账号密码),授权成功返回回掉地址。

第三方登入例子-GitHub授权登入(node-koa)

回掉地址中code就是返回的授权码,通过授权码再去获取令牌access_token

第三方登入例子-GitHub授权登入(node-koa)

授权回掉处理(获取access_token)

在第一步授权请求https://github.com/login/oauth/authorize成功后GitHub会给应用返回一个回掉http://localhost:3003/github/oauth/callback?code=14de2c737aa02037132d&state=1496989988474。这个回掉地址就是之前在GitHub注册应用时填入的回掉地址,另外还带了需要的code参数,state就是上一步请求中带的state参数,原样返回。

现在我们要对这个回掉请求进行处理:

//node-login/routes/github.js
const config = require('../config');
const router = require('koa-router')();
const fetch = require('node-fetch');
const routers = router
    .get('/login', async (ctx) => {
        ...
    })
    .get('/oauth/callback', async (ctx) => {
        const code = ctx.query.code;
        let path = 'https://github.com/login/oauth/access_token';
        const params = {
            client_id: config.client_id,
            client_secret: config.client_secret,
            code: code
        }
        console.log(code);
        await fetch(path, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(params)
        })
        .then(res => {
            return res.text();
        })
        .then(body => {
            ctx.body = body;
        })
       .catch(e => {
            console.log(e);
        })
    })
module.exports = routers;

GitHub返回回掉地址时,先拿到请求中的code参数,然后向https://github.com/login/oauth/access_token发送post请求并带上client_id,client_secret,code参数,请求成功后会返回带有access_token的信息。

第三方登入例子-GitHub授权登入(node-koa)

获取GitHub账号信息

最后带上获取的access_token请求https://api.github.com/user?access_token=xxx,返回的就是之前scope中对应的账号信息。

.get('/oauth/callback', async (ctx) => {
        const code = ctx.query.code;
        let path = 'https://github.com/login/oauth/access_token';
        const params = {
            client_id: config.client_id,
            client_secret: config.client_secret,
            code: code
        }
        console.log(code);
        await fetch(path, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(params)
        })
        .then(res => {
            return res.text();
        })
        .then(body => {
            const args = body.split('&');
            let arg = args[0].split('=');
            const access_token = arg[1];
            console.log(body);
            console.log(access_token);
            return access_token;
        })
        .then(async(token) => {
            const url = ' https://api.github.com/user?access_token=' + token;
            console.log(url);
            await fetch(url)
                .then(res => {
                    return res.json();
                })
                .then(res => {
                    console.log(res);
                    ctx.body = res;
                })
        })
        .catch(e => {
            console.log(e);
        })
    })

返回的用户信息如下:

第三方登入例子-GitHub授权登入(node-koa)

总结

用一张图来总结

第三方登入例子-GitHub授权登入(node-koa)

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Stella981 Stella981
3年前
Python+Selenium自动化篇
本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子。0.元素定位方法主要有:id定位:find\_element\_by\_id('')name定位:find\_element\_by\_name('')class定位:find\_element\_by\_class\_name(''
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
ISO27001信息安全管理体系
0x00前言初入甲方,刚开始接触的应该就是ISO27001信息安全管理体系,你拿到的应该就是一整套安全管理类的文档。在甲方,稍微有点规模的公司很注重制度和流程,岗位职责分工明细,那么这些安全管理制度,就是你所能掌控的游戏规则,几个人的信息安全部生存之道。0x01ISO27001简介ISO/IEC27001信息安全管理体系
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
暗箭伤人 暗箭伤人
1年前
【www.ithunter.club】 20230922下午
不容易的2023年,我们一起努力【www.ithunter.club】(2023092208:00:00.8872062023092216:00:00.887206)1.人事招聘专员数名(可选远程或入职)2.招聘向坐标东京Yahoo、Shift、L
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(