koa2服务端使用jwt进行鉴权及路由权限分发的流程分析


Posted in Javascript onJuly 22, 2019

大体思路

后端书写REST api时,有一些api是非常敏感的,比如获取用户个人信息,查看所有用户列表,修改密码等。如果不对这些api进行保护,那么别人就可以很容易地获取并调用这些 api 进行操作。

所以对于一些api,在调用之前,我们在服务端必须先对操作者进行“身份认证”,这就是所谓的鉴权。

Json Web Token 简称为 JWT,它定义了一种通信双方之间以 JSON 对象的形式安全传递信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名,复杂度较高,换来的是更可靠的安全系数。

整个认证的流程大体如下:

首先用户登录的接口是不用token认证的,因为这个接口本身就是token的产生来源。前端输入用户名和密码后请求服务器登录接口,服务器验证用户名密码正确后,生成token并返回给前端,前端存储token,并在后面的请求中把token带在请求头中传给服务器,服务器验证token有效,才可以进行下一步操作。

服务器生成token

由于我们的服务端使用 Koa2 框架进行开发,除了要使用到 jsonwebtoken 库之外,还要使用一个 koa-jwt 中间件,该中间件针对 Koa 对 jsonwebtoken 进行了封装,使用起来更加方便。

 const router = require('koa-router')();
const jwt = require('jsonwebtoken');
const userModel = require('../models/userModel.js');
router.post('/login', async (ctx) => {
 const data = ctx.request.body;const result = await userModel.findOne({
  name: data.name,
  password: data.password
 })
 if(result !== null){
  const token = jwt.sign({
   name: result.name,
   _id: result._id
  }, 'zhangnan', { expiresIn: '2h' });
  return ctx.body = {
   code: 200,
   token: token,
   msg: '登录成功'
  }
 }else{
  return ctx.body = {
   code: 400,
   token: null,
   msg: '用户名或密码错误'
  }
 }
});
module.exports = router;

(注意:这里暂时不讨论加盐加密校验,实际项目中密码不可能这样明文验证,这里只是为了着重讨论token鉴权。在验证了用户名密码正确之后,就可以调用 jsonwebtoken 的 sign() 方法来生成token,接收三个参数,第一个是载荷,用于编码后存储在 token 中的数据,也是验证 token 后可以拿到的数据;第二个是密钥,自己定义的,随便写个什么单词都可以,但是验证的时候一定要相同的密钥才能解码;第三个是options,可以设置 token 的过期时间。)

前端获取token

接下来就是前端获取 token,这里是在 vue.js 中使用 axios 进行请求,请求成功之后拿到 token 保存到 localStorage 中。

submit(){
 axios.post('/login', {
  name: this.username,
  password: this.password
 }).then(res => {
  if(res.code === 200){
   localStorage.setItem('token', res.data.token);
  }else{
   this.$message('登录失败')
  }
 })
}

然后前端在请求后端api时,就把 token 带在请求头中传给服务器进行验证。每次请求都要获取 localStorage 中的 token,这样很麻烦,这里使用了 axios 的请求拦截器,进行全局设置,对每次请求都进行了取 token 放到 headers 中的操作。

axios.interceptors.request.use(config => {
 const token = localStorage.getItem('token');
 config.headers.common['Authorization'] = 'Bearer ' + token;
 return config;
})

(这段代码,如果是vue项目,可以直接放在main.js中设置,表示每次请求前都会往请求头的authorization里塞一个token,至于那个Bearer 是koa-jwt的一个标识单词,方便解析)

服务器验证token

接下来服务器收到前端发过来的token后,就可以进行验证。

const koa = require('koa');
const koajwt = require('koa-jwt');
const app = new koa();

app.use(koajwt({
 secret: 'zhangnan'
}).unless({
  path: [/\/register/, /\/login/]
}));

(在这里没有定义错误处理函数,由于出现错误后会返回401,所以我直接就让前端来处理这种异常情况,给出一个错误的交互提示即可)

分析koa-jwt源码

我们在node_mudules里面找到koa-jwt/lib/resolvers文件夹下的auth-header.js文件,看下koa-jwt做了些什么

(可以看到它是先判断请求头中是否带了 authorization,如果有,则通过正则将 token 从 authorization 中分离出来,这里我们也看到了Bearer这个单词。如果没有 authorization,则代表了客户端没有传 token 到服务器,这时候就抛出 401 错误状态。)

再看看上一级的vertify.js。

(可以看到在 verify.js 中,它就是调用 jsonwebtoken 原生提供的 verify() 方法进行验证返回结果。jsonwebtoken 的 sign() 方法用于生成 token ,而 verify() 方法当然则是用来解析 token。属于jwt配对生产的两个方法,所以koa-jwt这个中间件也没做什么事,无非就是用正则解析请求头,调用jwt的vertify方法验证token,在koa-jwt文件夹的index.js中,koa-jwt还调用koa-unless进行路由权限分发)

以上就是json web token的大体流程。

总结

以上所述是小编给大家介绍的koa2服务端使用jwt进行鉴权及路由权限分发的流程分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
如何实现浏览器上的右键菜单
Jul 10 Javascript
script标签属性type与language使用选择
Dec 02 Javascript
Js(JavaScript)中,弹出是或否的选择框示例(confirm用法的实例分析)
Jul 09 Javascript
jquery中获得元素尺寸和坐标的方法整理
May 18 Javascript
js实现checkbox全选、不选与反选的方法
Feb 09 Javascript
jquery过滤特殊字符',防sql注入的实现方法
Aug 17 Javascript
解析如何利用iframe标签以及js制作时钟
Dec 08 Javascript
一句jQuery代码实现返回顶部效果(简单实用)
Dec 28 Javascript
JS获取鼠标位置距浏览器窗口距离的方法示例
Apr 11 Javascript
使用原生js写ajax实例(推荐)
May 31 Javascript
vue.js表单验证插件(vee-validate)的使用教程详解
May 23 Javascript
jquery插件实现代码雨特效
Apr 24 jQuery
在小程序中推送模板消息的实现方法
Jul 22 #Javascript
javascript自定义日期比较函数用法示例
Jul 22 #Javascript
详解微信小程序自定义组件的实现及数据交互
Jul 22 #Javascript
教你30秒发布一个TypeScript包到NPM的方法步骤
Jul 22 #Javascript
详解vue为什么要求组件模板只能有一个根元素
Jul 22 #Javascript
微信小程序获取用户绑定手机号方法示例
Jul 21 #Javascript
Vue商品控件与购物车联动效果的实例代码
Jul 21 #Javascript
You might like
PHP开发文件系统实例讲解
2006/10/09 PHP
php抓即时股票信息
2006/10/09 PHP
解析php中如何直接执行SHELL
2013/06/28 PHP
php设计模式之模板模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
Gambit vs CL BO3 第一场 2.13
2021/03/10 DOTA
复制Input内容的js代码_支持所有浏览器,修正了Firefox3.5以上的问题
2010/06/21 Javascript
JavaScript 对象模型 执行模型
2010/10/15 Javascript
javascript 学习笔记(onchange等)
2010/11/14 Javascript
关于js数组去重的问题小结
2014/01/24 Javascript
jquery实现在页面加载完毕后获取图片高度或宽度
2014/06/16 Javascript
jquery序列化表单以及回调函数的使用示例
2014/07/02 Javascript
js HTML5多媒体影音播放
2016/10/17 Javascript
Angular ng-repeat遍历渲染完页面后执行其他操作详细介绍
2016/12/13 Javascript
js+css实现打字效果
2020/06/24 Javascript
VUE实时监听元素距离顶部高度的操作
2020/07/29 Javascript
[43:03]LGD vs Newbee 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/19 DOTA
Python __setattr__、 __getattr__、 __delattr__、__call__用法示例
2015/03/06 Python
Python语言的面相对象编程方式初步学习
2016/03/12 Python
基于Python 的进程管理工具supervisor使用指南
2016/09/18 Python
python实现下载文件的三种方法
2017/02/09 Python
TensorFlow 实战之实现卷积神经网络的实例讲解
2018/02/26 Python
Python 实现网页自动截图的示例讲解
2018/05/17 Python
python操作mysql代码总结
2018/06/01 Python
Python 中字符串拼接的多种方法
2018/07/30 Python
python使用celery实现异步任务执行的例子
2019/08/28 Python
Python常用数据类型之间的转换总结
2019/09/06 Python
Python3 全自动更新已安装的模块实现
2020/01/06 Python
BSTN意大利:德国街头和运动文化高品质商店
2020/12/22 全球购物
SQL Server的固定数据库角色都有哪些?对应的服务器权限有哪些?
2013/05/18 面试题
写一个函数,要求输入一个字符串和一个字符长度,对该字符串进行分隔
2015/07/30 面试题
煤矿班组长的职责
2013/12/25 职场文书
服务之星获奖感言
2014/01/21 职场文书
五分钟演讲稿
2014/04/30 职场文书
学习型党组织心得体会
2014/09/12 职场文书
渠道运营商合作协议书范本
2014/10/06 职场文书
React列表栏及购物车组件使用详解
2021/06/28 Javascript