前言

JWT(JSON Web Token),是为了在网络环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519)。

更多的介绍和说明,以及各种原理,我在此就不多赘诉了。JWT不是一个新鲜的东西,网上相关的介绍已经非常多了。不是很了解的可以在网上搜索一下相关信息。

源码

Talk is cheap. Show me the code.

工作流程

JWT本质来说是一个token。在前后端进行HTTP连接时来进行相应的验证。

  1. 博客的后台管理系统发起登录请求,后端服务器校验成功之后,生成JWT认证信息;
  2. 前端接收到JWT后进行存储;
  3. 前端在之后每次接口调用发起HTTP请求时,会将JWT放到HTTP的headers参数里的authorization中一起发送给后端;
  4. 后端接收到请求时会根据JWT中的信息来校验当前发起HTTP请求的用户是否是具有访问权限的,有访问权限时则交给服务器继续处理,没有时则直接返回401错误。

实现过程

1. 登录成功生成JWT

说明:以下代码只保留了核心代码,详细代码可在对应文件中查看,下同。

// /server/api/admin/admin.controller.js
const jwt = require('jsonwebtoken');
const config = require('../../config/config'); exports.login = async(ctx) => {
// ...
if (hashedPassword === hashPassword) {
// ...
// 用户token
const userToken = {
name: userName,
id: results[0].id
};
// 签发token
const token = jwt.sign(userToken, config.tokenSecret, { expiresIn: '2h' });
// ...
}
// ...
}

2. 添加中间件校验JWT

// /server/middlreware/tokenError.js
const jwt = require('jsonwebtoken');
const config = require('../config/config');
const util = require('util');
const verify = util.promisify(jwt.verify); /**
* 判断token是否可用
*/
module.exports = function () {
return async function (ctx, next) {
try {
// 获取jwt
const token = ctx.header.authorization;
if (token) {
try {
// 解密payload,获取用户名和ID
let payload = await verify(token.split(' ')[1], config.tokenSecret);
ctx.user = {
name: payload.name,
id: payload.id
};
} catch (err) {
console.log('token verify fail: ', err)
}
}
await next();
} catch (err) {
if (err.status === 401) {
ctx.status = 401;
ctx.body = {
success: 0,
message: '认证失败'
};
} else {
err.status = 404;
ctx.body = {
success: 0,
message: '404'
};
}
}
}
}

3. Koa.js中添加JWT处理

此处在开发时需要过滤掉登录接口(login),否则会导致JWT验证永远失败。

// /server/config/koa.js
const jwt = require('koa-jwt');
const tokenError = require('../middlreware/tokenError');
// ... const app = new Koa(); app.use(tokenError());
app.use(bodyParser());
app.use(koaJson());
app.use(resource(path.join(config.root, config.appPath))); app.use(jwt({
secret: config.tokenSecret
}).unless({
path: [/^\/backapi\/admin\/login/, /^\/blogapi\//]
})); module.exports = app;

4.前端处理

前端开发使用的是Vue.js,发送HTTP请求使用的是axios。

  1. 登录成功之后将JWT存储到localStorage中(可根据个人需要存储,我个人是比较喜欢存储到localStorage中)。

    methods: {
    login: async function () {
    // ... let res = await api.login(this.userName, this.password);
    if (res.success === 1) {
    this.errMsg = '';
    localStorage.setItem('DON_BLOG_TOKEN', res.token);
    this.$router.push({ path: '/postlist' });
    } else {
    this.errMsg = res.message;
    }
    }
    }

  2. Vue.js的router(路由)跳转前校验JWT是否存在,不存在则跳转到登录页面。

    // /src/router/index.js
    router.beforeEach((to, from, next) => {
    if (to.meta.requireAuth) {
    const token = localStorage.getItem('DON_BLOG_TOKEN');
    if (token && token !== 'null') {
    next();
    } else {
    next('/login');
    }
    } else {
    next();
    }
    });

  3. axios拦截器中给HTTP统一添加Authorization信息

    // /src/fetch/fetch.js
    axios.interceptors.request.use(
    config => {
    const token = localStorage.getItem('DON_BLOG_TOKEN');
    if (token) {
    // Bearer是JWT的认证头部信息
    config.headers.common['Authorization'] = 'Bearer ' + token;
    }
    return config;
    },
    error => {
    return Promise.reject(error);
    }
    );

  4. axios拦截器在接收到HTTP返回时统一处理返回状态

    // /src/main.js
    axios.interceptors.response.use(
    response => {
    return response;
    },
    error => {
    if (error.response.status === 401) {
    Vue.prototype.$msgBox.showMsgBox({
    title: '错误提示',
    content: '您的登录信息已失效,请重新登录',
    isShowCancelBtn: false
    }).then((val) => {
    router.push('/login');
    }).catch(() => {
    console.log('cancel');
    });
    } else {
    Vue.prototype.$message.showMessage({
    type: 'error',
    content: '系统出现错误'
    });
    }
    return Promise.reject(error);
    }
    );

总结

到这里整个流程就走完了。当然单纯的JWT并不是说绝对安全的,不过对于一个个人博客系统的认证来说还是足够的。

最后打个小广告。目前正在开发新版的个人博客中,包括前端后端两部分,都已在GitHub上开源,目前在逐步完善功能中。欢迎感兴趣的同学fork和star。

个人博客开发系列:Vue.js + Koa.js项目中使用JWT认证的更多相关文章

  1. sau交流学习社区--songEagle开发系列:Vue.js + Koa.js项目中使用JWT认证

    一.前言 JWT(JSON Web Token),是为了在网络环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519). JWT不是一个新鲜的东西,网上相关的介绍已经非常多了.不是很了解的 ...

  2. Django个人博客开发 | 前言

    本渣渣不专注技术,只专注使用技术,不是一个资深的coder,是一个不折不扣的copier 1.前言 自学 Python,始于 Django 框架,Scrapy 框架,elasticsearch搜索引擎 ...

  3. django 简易博客开发 3 静态文件、from 应用与自定义

    首先还是贴一下源代码地址  https://github.com/goodspeedcheng/sblog 上一篇博客我们介绍了 django 如何在views中使用templates以及一些常用的数 ...

  4. Django博客开发-数据建模与样式设定

    开发流程介绍 之前Django的学习过程当中已经把基本Django开发学完了,现在以Django 的博客项目完成一遍课程的回顾和总结.同时来一次完整开发的Django体验. 一个产品从研究到编码我们要 ...

  5. Padrino 博客开发示例

    英文版出处:http://www.padrinorb.com/guides/blog-tutorial 楼主按 拿作者自己的话说:Padrino(谐音:派骓诺)是一款基于Sinatra的优雅的Web应 ...

  6. 【全网最全的博客美化系列教程】08.自定义地址栏Logo

    全网最全的博客美化系列教程相关文章目录 [全网最全的博客美化系列教程]01.添加Github项目链接 [全网最全的博客美化系列教程]02.添加QQ交谈链接 [全网最全的博客美化系列教程]03.给博客添 ...

  7. 【全网最全的博客美化系列教程】01.添加Github项目链接

    全网最全的博客美化系列教程相关文章目录 [全网最全的博客美化系列教程]01.添加Github项目链接 [全网最全的博客美化系列教程]02.添加QQ交谈链接 [全网最全的博客美化系列教程]03.给博客添 ...

  8. 【全网最全的博客美化系列教程】02.添加QQ交谈链接

    全网最全的博客美化系列教程相关文章目录 [全网最全的博客美化系列教程]01.添加Github项目链接 [全网最全的博客美化系列教程]02.添加QQ交谈链接 [全网最全的博客美化系列教程]03.给博客添 ...

  9. Django博客开发实践,初学者开发经验

    python,Django初学者,开发简易博客,做了一下笔记,记录了开发的过程,功力浅薄,仅供初学者互相 交流,欢迎意见建议.具体链接:Django博客开发实践(一)--分析需求并创建项目 地址:ht ...

随机推荐

  1. Jmeter压力测试笔记(5)问题原因

    压测链路是jmeter=>slb=>nginx => php=>rds 报 Too Many Connections 的原因是前端同时保持了 16000 个连接,达到实例规格的 ...

  2. 关于微信小程序的一点经验

    2018年的11月份,自己做微信小程序相关的项目已经有四个月,这四个月自己走过很多弯路,也学到了不少经验,下面就一一总结: 一,微信小程序的radio组件是可以改变按钮样式的(比如大小,颜色等等) 改 ...

  3. Adb adb push (remote write failed: No space left on device)

    修改完成程序后, mm 后, 准备要push 进到公司测试手机里面的.之前还真的没有遇到过这个问题,查了一下, 应该是手机没空间了的 sudo adb root sudo adb remount su ...

  4. Java第二十五天,多线程之等待唤醒机制

    当线程被创建并且被启动之后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,而是具有以下多种状态: 这六种状态之间的转换关系如下: 1.等待唤醒机制 注意: (1)两个线程之间必须用同步代码块 ...

  5. Mysql中的分库分表

    mysql中的分库分表分库:减少并发问题分表:降低了分布式事务分表 1.垂直分表 把其中的不常用的基础信息提取出来,放到一个表中通过id进行关联.降低表的大小来控制性能,但是这种方式没有解决高数据量带 ...

  6. IDEA默认KeyMap映射快捷键

    编辑 快捷键 描述 Ctrl + 空格 基础代码补全(任意类.方法.变量的名字) Ctrl + Shift + 空格 智能代码补全(过滤期望类型的方法和变量列表) Ctrl + Shift + 回车 ...

  7. Win8.1/Win10在某些程序输入中文变成问号的解决方法

    之前我是使用Win8.1,在某些软件上输入中文,却显示问号,换输入法也没用,当时也没用太在意,后来升级到Win10还是一样.同样的软件在其它Win8.1/Win10电脑却可以正常显示中文. 解决方法如 ...

  8. break与continue对比

    - break 用来终止循环 - continue 用来跳出当前循环,继续下次循环 // 求1到100之间所有不能被3整除的整数的第一个大于2000的和 var sum = 0; for(var i= ...

  9. 关于gpu版本的tensorflow+anaconda+jupyter的一些安装问题(持续更新)

    关于anaconda安装,虽然清华镜像站资源很丰富,但是不知道是网络还是运气的问题,用这个路径安装的时候总是出现文件丢失.具体表现可能是anaconda prompt 找不到,conda命令无效等问题 ...

  10. c语言中的引用使用

    最近在写一个图像处理的程序时候,遇到一些传参的问题,最后发现引用的效率高一些,在此提醒各位道友,多多关注引用的应用及使用. 1.在引用的使用中,单纯给某个变量取个别名是毫无意义的,不要为了耍酷而乱用, ...