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 相关文章推荐
20个非常棒的 jQuery 幻灯片插件和教程分享
Aug 23 Javascript
js中的hasOwnProperty和isPrototypeOf方法使用实例
Jun 06 Javascript
js实现仿阿里巴巴城市选择框效果实例
Jun 24 Javascript
JS模仿手机端九宫格登录功能实现代码
Apr 28 Javascript
使用AJAX实现Web页面进度条的实例分享
May 06 Javascript
微信js-sdk地理位置接口用法示例
Oct 12 Javascript
解析如何利用iframe标签以及js制作时钟
Dec 08 Javascript
JavaScript实现倒计时跳转页面功能【实用】
Dec 13 Javascript
js 去掉字符串前后空格实现代码集合
Mar 25 Javascript
vue2 mint-ui loadmore实现下拉刷新,上拉更多功能
Mar 21 Javascript
解决vue热替换失效的根本原因
Sep 19 Javascript
用node撸一个监测复联4开售短信提醒的实现代码
Apr 10 Javascript
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
ThinkPHP关联模型操作实例分析
2012/09/23 PHP
使用PHP静态变量当缓存的方法
2013/11/13 PHP
Yii2中cookie用法示例分析
2016/07/18 PHP
PHP实现的一致性Hash算法详解【分布式算法】
2018/03/31 PHP
使用vs code编辑调试php配置的方法
2019/01/29 PHP
一个刚完成的layout(拖动流畅,不受iframe影响)
2007/08/17 Javascript
JS写的数字拼图小游戏代码[学习参考]
2008/10/29 Javascript
JS 字符串连接[性能比较]
2009/05/10 Javascript
JavaScript DOM 学习第九章 选取范围的介绍
2010/02/19 Javascript
ASP.NET jQuery 实例6 (实现CheckBoxList成员全选或全取消)
2012/01/13 Javascript
JS解析json数据并将json字符串转化为数组的实现方法
2012/12/25 Javascript
js获取当前路径的简单示例代码
2014/01/08 Javascript
JS实现可缩放、拖动、关闭和最小化的浮动窗口完整实例
2015/03/04 Javascript
详解jQuery向动态生成的内容添加事件响应jQuery live()方法
2015/11/02 Javascript
Angularjs中的事件广播 —全面解析$broadcast,$emit,$on
2016/05/17 Javascript
JavaScript操作 url 中 search 部分方法函数
2016/06/15 Javascript
jQuery 移动端拖拽(模块化开发,触摸事件,webpack)
2016/10/28 Javascript
JavaScript拖动层Div代码
2017/03/01 Javascript
JavaScript实现简单生成随机颜色的方法
2017/09/21 Javascript
聊聊Vue.js的template编译的问题
2017/10/09 Javascript
[02:57]DOTA2亚洲邀请赛小组赛第四日 赛事回顾
2015/02/02 DOTA
python批量同步web服务器代码核心程序
2014/09/01 Python
python传递参数方式小结
2015/04/17 Python
python字符串编码识别模块chardet简单应用
2015/06/15 Python
Python字典中的键映射多个值的方法(列表或者集合)
2018/10/17 Python
Python实现密码薄文件读写操作
2019/12/16 Python
浅谈Python3实现两个矩形的交并比(IoU)
2020/01/18 Python
python GUI库图形界面开发之PyQt5工具栏控件QToolBar的详细使用方法与实例
2020/02/28 Python
k-means 聚类算法与Python实现代码
2020/06/01 Python
让IE下支持Html5的placeholder属性的插件
2014/09/02 HTML / CSS
HTML5新特性之用SVG绘制微信logo
2016/02/03 HTML / CSS
使用HTML5在网页中嵌入音频和视频播放的基本方法
2016/02/22 HTML / CSS
HTML5新特性 多线程(Worker SharedWorker)
2017/04/24 HTML / CSS
音乐教育专业自荐信
2014/09/18 职场文书
乡领导班子四风问题对照检查材料
2014/09/25 职场文书
MySQL聚簇索引和非聚簇索引的区别详情
2022/06/14 MySQL