koa+jwt实现token验证与刷新功能


Posted in Javascript onMay 30, 2019

JWT

JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

本文只讲Koa2 + jwt的使用,不了解JWT的话请到这里)进行了解。

koa环境

要使用koa2+jwt需要先有个koa的空环境,搭环境比较麻烦,我直接使用koa起手式,这是我使用koa+typescript搭建的空环境,如果你也经常用koa写写小demo,可以点个star,方便~

安装koa-jwt

koa-jwt主要作用是控制哪些路由需要jwt验证,哪些接口不需要验证:

import * as koaJwt from 'koa-jwt';
//路由权限控制 除了path里的路径不需要验证token 其他都要
app.use(
  koaJwt({
    secret: secret.sign
  }).unless({
    path: [/^\/login/, /^\/register/]
  })
);

上面代码中,除了登录、注册接口不需要jwt验证,其他请求都需要。

使用jsonwebtoken生成、验证token

执行npm install jsonwebtoken安装jsonwebtoken

相关代码:

import * as jwt from 'jsonwebtoken';
const secret = 'my_app_secret';
const payload = {user_name:'Jack', id:3, email: '1234@gmail.com'};
const token = jwt.sign(payload, secret, { expiresIn: '1h' });

上面代码中通过jwt.sign来生成一个token,

参数意义:

  • payload:载体,一般把用户信息作为载体来生成token
  • secret:秘钥,可以是字符串也可以是文件
  • expiresIn:过期时间 1h表示一小时

在登录中返回token

import * as crypto from 'crypto';
import * as jwt from 'jsonwebtoken';
async login(ctx){
 //从数据库中查找对应用户
 const user = await userRespository.findOne({
  where: {
   name: user.name
  }
 });
 //密码加密
 const psdMd5 = crypto
  .createHash('md5')
  .update(user.password)
  .digest('hex');
 //比较密码的md5值是否一致 若一致则生成token并返回给前端
 if (user.password === psdMd5) {
  //生成token
  token = jwt.sign(user, secret, { expiresIn: '1h' });
  //响应到前端
  ctx.body = {
   token
  }
 }
}

前端拦截器

前端通过登录拿到返回过来的token,可以将它存在localStorage里,然后再以后的请求中把token放在请求头的Authorization里带给服务端。

这里以axios请求为例,在发送请求时,通过请求拦截器把token塞到header里:

//请求拦截器
axios.interceptors.request.use(function(config) {
  //从localStorage里取出token
  const token = localStorage.getItem('tokenName');
  //把token塞入Authorization里
  config.headers.Authorization = `Bearer ${token}`;
  
  return config;
 },
 function(error) {
  // Do something with request error
  return Promise.reject(error);
 }
);

服务端处理前端发送过来的Token
前端发送请求携带token,后端需要判断以下几点:

token是否正确,不正确则返回错误
token是否过期,过期则刷新token 或返回401表示需要从新登录

关于上面两点,需要在后端写一个中间件来完成:

app.use((ctx, next) => {
 if (ctx.header && ctx.header.authorization) {
  const parts = ctx.header.authorization.split(' ');
  if (parts.length === 2) {
   //取出token
   const scheme = parts[0];
   const token = parts[1];
   if (/^Bearer$/i.test(scheme)) {
    try {
     //jwt.verify方法验证token是否有效
     jwt.verify(token, secret.sign, {
      complete: true
     });
    } catch (error) {
     //token过期 生成新的token
     const newToken = getToken(user);
     //将新token放入Authorization中返回给前端
     ctx.res.setHeader('Authorization', newToken);
    }
   }
  }
 }
 return next().catch(err => {
  if (err.status === 401) {
   ctx.status = 401;
   ctx.body =
    'Protected resource, use Authorization header to get access\n';
  } else {
   throw err;
  }});
 });

上面中间件是需要验证token时都需要走这里,可以理解为拦截器,在这个拦截器中处理判断token是否正确及是否过期,并作出相应处理。

后端刷新token 前端需要更新token
后端更换新token后,前端也需要获取新token 这样请求才不会报错。

由于后端更新的token是在响应头里,所以前端需要在响应拦截器中获取新token。

依然以axios为例:

//响应拦截器
axios.interceptors.response.use(function(response) {
  //获取更新的token
  const { authorization } = response.headers;
  //如果token存在则存在localStorage
  authorization && localStorage.setItem('tokenName', authorization);
  return response;
 },
 function(error) {
  if (error.response) {
   const { status } = error.response;
   //如果401或405则到登录页
   if (status == 401 || status == 405) {
    history.push('/login');
   }
  }
  return Promise.reject(error);
 }
);

总结

以上所述是小编给大家介绍的koa+jwt实现token验证与刷新功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JQuery jsonp 使用示例代码
Aug 12 Javascript
jquery trim() 功能源代码
Feb 14 Javascript
BootStrap的JS插件之轮播效果案例详解
May 16 Javascript
Vue实现双向绑定的方法
Dec 22 Javascript
canvas绘制万花筒效果(代码分享)
Jan 20 Javascript
JS去掉字符串前后空格、阻止表单提交的实现代码
Jun 08 Javascript
vue init失败简单解决方法(终极版)
Dec 22 Javascript
Vue 中使用 CSS Modules优雅方法
Apr 09 Javascript
webpack项目轻松混用css module的方法
Jun 12 Javascript
vue+springmvc导出excel数据的实现代码
Jun 27 Javascript
40行代码把Vue3的响应式集成进React做状态管理
May 20 Javascript
解决vue-pdf查看pdf文件及打印乱码的问题
Nov 04 Javascript
深入理解JavaScript 箭头函数
May 30 #Javascript
socket在egg中的使用实例代码详解
May 30 #Javascript
深入了解JavaScript 私有化
May 30 #Javascript
jQuery模拟html下拉多选框的原生实现方法示例
May 30 #jQuery
Vue CL3 配置路径别名详解
May 30 #Javascript
Vue CLI3中使用compass normalize的方法
May 30 #Javascript
通过实践编写优雅的JavaScript代码
May 30 #Javascript
You might like
为查询结果建立向后/向前按钮
2006/10/09 PHP
解析PHP缓存函数的使用说明
2013/05/10 PHP
浅谈php提交form表单
2015/07/01 PHP
PHP开发中常用的十个代码样例
2016/02/02 PHP
Laravel多用户认证系统示例详解
2018/03/13 PHP
mongodb和php的用法详解
2019/03/25 PHP
laravel与thinkphp之间的区别与优缺点
2021/03/02 PHP
js 页面执行时间计算代码
2009/03/04 Javascript
用js做一个小游戏平台 (一)
2009/12/29 Javascript
jQuery 工具函数学习资料
2010/04/29 Javascript
一个JavaScript函数把URL参数解析成Json对象
2014/09/24 Javascript
利用yarn实现一个webpack+react种子
2016/10/25 Javascript
vue 修改 data 数据问题并实时显示的方法
2018/08/27 Javascript
Vue项目History模式404问题解决方法
2018/10/31 Javascript
vue.js的vue-cli脚手架中使用百度地图API的实例
2019/01/21 Javascript
Vue中Table组件Select的勾选和取消勾选事件详解
2019/03/19 Javascript
微信公众平台 客服接口发消息的实现代码(Java接口开发)
2019/04/17 Javascript
React传值 组件传值 之间的关系详解
2019/08/26 Javascript
Layui 动态禁止select下拉的例子
2019/09/03 Javascript
vue改变循环遍历后的数据实例
2019/11/07 Javascript
Vue实现可移动水平时间轴
2020/06/29 Javascript
vue style width a href动态拼接问题的解决
2020/08/07 Javascript
[49:35]LGD vs OG 2018国际邀请赛淘汰赛BO3 第二场 8.25
2018/08/29 DOTA
python实现批量获取指定文件夹下的所有文件的厂商信息
2014/09/28 Python
http请求 request失败自动重新尝试代码示例
2018/01/25 Python
python实现合并多个list及合并多个django QuerySet的方法示例
2019/06/11 Python
Pycharm简单使用教程(入门小结)
2019/07/04 Python
pytorch中的上采样以及各种反操作,求逆操作详解
2020/01/03 Python
如何在django中实现分页功能
2020/04/22 Python
python 实现PIL模块在图片画线写字
2020/05/16 Python
省级四好少年事迹材料
2014/01/25 职场文书
群众路线教育实践活动个人对照检查材料思想汇报(社区班子)
2014/10/06 职场文书
学生通报表扬范文
2015/05/04 职场文书
工作调动申请报告
2015/05/18 职场文书
浅谈pytorch中stack和cat的及to_tensor的坑
2021/05/20 Python
Django实现WebSocket在线聊天室功能(channels库)
2021/09/25 Python