Vue路由之JWT身份认证的实现方法


Posted in Javascript onAugust 26, 2019

一、JWT身份认证简介

JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案,相较于session机制,服务器就不需要保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。JWT 实际上是一个令牌(Token),服务器会将一些元数据、指定的secret进行签名并生成token,并返回给客户端,客户端得到这个服务器返回的令牌后,需要将其存储到 Cookie 或 localStorage 中,此后,每次与服务器通信都要带上这个令牌,可以把它放到 Cookie 中自动发送,但这样做不能跨域,所以更好的做法是将其放到 HTTP 请求头 Authorization 字段里面。

二、JWT的使用

① 安装并引入jsonwebtoken模块;
② 对元数据、secret密钥进行签名,并生成对应的token;
③ 对token进行校验是否过期;

const jwt = require("jsonwebtoken"); // 引入jwt
const secret = "this is a private key"; // 指定一个用于生成token的密钥字符串
const token = jwt.sign({ foo: 'bar' }, secret, { // 传入元数据和secret密钥,并指定过期时间生成token
  expiresIn: 5, // 单独一个数字表示多少秒
  // expiresIn: "10h", // 表示10小时后过期
  // expiresIn: "2d" // 表示2天后过期
});
console.log(`token is ${token}`);
setTimeout(() => { // 5秒后对该token进行校验
  jwt.verify(token, secret, (err, decoded) => {
    console.log(err);
    if (err) {
      console.log('token 已经失效了.');
    } else {
      console.log(`token data is ${JSON.stringify(decoded)}`);
    }
  });
}, 5000);

生成的token为一个很长的字符串,分为三部分,每部分由.号隔开,即 头部.载荷.签名,5秒后token校验结果为error,即token已经过期,校验的时候,会得到token的解码数据,主要包括生成token时候的元数据、token的签发时间(iat)、token的过期时间(exp)

// 生成的token字符串为
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE1NjY3MzE4MzEsImV4cCI6MTU2NjczMTgzNn0.cZZkExNnVqBtnfQN2vtU2Z7JB0PBo1CFyC5NiOywg54
// token decoded后的数据
token data is {"foo":"bar","iat":1566731831,"exp":1566731836}

三、封装axios

由于在使用jwt认证的时候,客户端向服务器发起请求的时候,都要带上token,即要获取到token并将其放到请求头的Authorization字段中,服务器才能从authorization中取出token并进行校验,所以我们必须通过拦截器去实现,在每次请求之前将请求进行拦截,然后添加上token,再继续向服务器发起请求。

import axios from "axios";
class Request {
  constructor() {
    this.baseURL = process.env.NODE_ENV === 'development' ? 'http://localhost:3000' : '/'; // 设置请求baseURL
    this.timeout = 2000; // 设置请求超时时间
  }
  request(config){// 这里的config是请求的时候传递的参数配置对象,比如url、method、data等
    const instance = axios.create({ // 创建axios实例
      baseURL: this.baseURL,
      timeout: this.timeout,
    });
    // 设置拦截器
    instance.interceptors.request.use((config) => { // 请求拦截之后就是要使用这个config, config表示整个请求对象
      config.headers.Authorization = localStorage.getItem('token'); // 将token从localStorage中取出并添加到请求头的Authorization字段上
      return config; // 返回请求对象,继续向服务器发起请求
    }, err => Promise.reject(err));
    // 设置响应拦截器
    instance.interceptors.response.use(res => res.data, err => Promise.reject(err));
  
    return instance(config);
  }
}
export default new Request();

四、通过路由钩子进行登录校验

我们需要在路由跳转之前,进行登录校验,即校验登录的token是否已经过期,如果token没有失效,则可以继续访问页面;如果token已经失效,那么检查一下所访问的页面是否需要登录才能访问,如果是需要登录后才能访问,那么跳转到登录页面;如果是不需要登录也能访问的页面则继续访问;

const whiteList = ["/"]; // 定义一个白名单列表
router.beforeEach(async (to, from, next) => {
 if (whiteList.includes(to.path)) { // 如果是访问的白名单中的页面
  return next(); // 不需要校验,直接返回继续访问该页面
 }
 const isTokenAvailable = await store.dispatch('validate'); // 校验token是否失效
 if (isTokenAvailable) { // 如果token未失效
  if(to.path === "/login") { // 如果访问的是login页面,则回到首页
   next("/");
  } else { // 如果访问的不是login页面,则继续访问当前要访问的页面
   next();
  }
 } else { // 如果token失效了
  const needLogin = to.matched.some(item => item.meta.needLogin); // 检测要访问的页面是否需要登录才能访问
  if(needLogin) { // 如果访问的页面是需要登录的
   next("/login"); // 跳转到登录页面
  } else { // 如果访问的页面是不需要登录的,则直接继续访问
   next();
  }
 }
});

上面item.meta.needLogin,这个needLogin是在router中进行自定义配置的,在配置路由的时候,允许通过meta属性配置一些自定义的元数据,如下所示:

export default new Router({
 routes: [
  {
   path: '/profile',
   name: 'profile',
   component: Profile,
   meta: {needLogin: true}
  }
 ]
})

五、总结

jwt认证,主要就是Vue路由钩子beforeEach()的应用,以及请求拦截器的封装,在每次路由跳转前进行token认证(校验),检测token是否失效,其校验过程就是向服务器发起一个请求,比如"/validate",由于客户端请求拦截器的作用,会在发起"/validate"请求之前,在请求头的Authorization字段加上token,服务器收到token后就能对token是否有效进行校验了,然后返回token校验结果,客户端再根据token的校验结果进行路由的具体跳转。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
让html页面不缓存js的实现方法
Oct 31 Javascript
jQuery设置指定网页元素宽度和高度的方法
Mar 25 Javascript
JS实现的3D拖拽翻页效果代码
Oct 31 Javascript
JavaScript 闭包详细介绍
Sep 28 Javascript
js事件源window.event.srcElement兼容性写法(详解)
Nov 25 Javascript
使用BootStrap实现悬浮窗口的效果
Dec 13 Javascript
微信小程序 仿美团分类菜单 swiper分类菜单
Apr 12 Javascript
jQuery实现的老虎机跑动效果示例
Dec 29 jQuery
微信小程序与公众号卡券/会员打通的问题
Jul 25 Javascript
node.js中stream流中可读流和可写流的实现与使用方法实例分析
Feb 13 Javascript
小程序按钮避免多次调用接口和点击方案实现(不用showLoading)
Apr 15 Javascript
解读Vue组件注册方式
May 15 Vue.js
Vue中跨域及打包部署到nginx跨域设置方法
Aug 26 #Javascript
js实现跟随鼠标移动的小球
Aug 26 #Javascript
vue 源码解析之虚拟Dom-render
Aug 26 #Javascript
Node.js爬虫如何获取天气和每日问候详解
Aug 26 #Javascript
vue移动端实现手机左右滑动入场动画
Jun 17 #Javascript
详解vuex数据传输的两种方式及this.$store undefined的解决办法
Aug 26 #Javascript
JS阻止事件冒泡的方法详解
Aug 26 #Javascript
You might like
十天学会php之第四天
2006/10/09 PHP
《PHP边学边教》(04.编写简易的通讯录――视频教程1)
2006/12/13 PHP
PHP--用万网的接口实现域名查询功能
2012/12/13 PHP
分享下页面关键字抓取www.icbase.com站点代码(带asp.net参数的)
2014/01/30 PHP
Yii2.0表关联查询实例分析
2016/07/18 PHP
thinkPHP多语言切换设置方法详解
2016/11/11 PHP
彻底搞懂PHP 变量结构体
2017/10/11 PHP
laravel框架语言包拓展实现方法分析
2019/11/22 PHP
PHP超级全局变量【$GLOBALS,$_SERVER,$_REQUEST等】用法实例分析
2019/12/11 PHP
文字幻灯片
2006/06/26 Javascript
两个SUBMIT按钮,如何区分处理
2006/08/22 Javascript
Google韩国首页图标动画效果
2007/08/26 Javascript
Ext 今日学习总结
2010/09/19 Javascript
20个非常棒的 jQuery 幻灯片插件和教程分享
2011/08/23 Javascript
jQuery基本选择器选择元素使用介绍
2013/04/18 Javascript
纯js实现div内图片自适应大小(已测试,兼容火狐)
2014/06/16 Javascript
APP中javascript+css3实现下拉刷新效果
2016/01/27 Javascript
jQuery使用zTree插件实现树形菜单和异步加载
2016/02/25 Javascript
微信小程序开发图片拖拽实例详解
2017/05/05 Javascript
JavaScript实现的浏览器下载文件的方法
2017/08/09 Javascript
vue源码解析之事件机制原理
2018/04/21 Javascript
详解Angular路由之路由守卫
2018/05/10 Javascript
深入浅析Vue中mixin和extend的区别和使用场景
2019/08/01 Javascript
JavaScript设计模式之策略模式实现原理详解
2020/05/29 Javascript
[56:56]VG vs LGD 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.22
2019/09/05 DOTA
简单了解Python下用于监视文件系统的pyinotify包
2015/11/13 Python
Python基于opencv实现的简单画板功能示例
2019/03/04 Python
Python实现新型冠状病毒传播模型及预测代码实例
2020/02/05 Python
HTML5之SVG 2D入门1—SVG(可缩放矢量图形)概述
2013/01/30 HTML / CSS
什么叫做SQL注入,如何防止
2016/10/04 面试题
请说出这段代码执行后a和b的值分别是多少
2015/03/28 面试题
机械化及自动化毕业生的自我评价分享
2013/11/06 职场文书
学校安全责任书
2014/04/14 职场文书
2015年班主任个人工作总结
2015/03/31 职场文书
Python中常见的反爬机制及其破解方法总结
2021/06/10 Python
Python爬虫入门案例之爬取二手房源数据
2021/10/16 Python