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 相关文章推荐
25个好玩的JavaScript小游戏分享
Apr 22 Javascript
js document.write()使用介绍
Feb 21 Javascript
JavaScript中字符串拼接的基本方法
Jul 07 Javascript
javascript实现省市区三级联动下拉框菜单
Nov 17 Javascript
node.js实现爬虫教程
Aug 25 Javascript
什么是JavaScript注入攻击?
Sep 14 Javascript
微信小程序 获取微信OpenId详解及实例代码
Oct 31 Javascript
详解AngularJS通过ocLazyLoad实现动态(懒)加载模块和依赖
Mar 01 Javascript
JavaScript实现简单的四则运算计算器完整实例
Apr 28 Javascript
Jquery实现无缝向上循环滚动列表的特效
Feb 13 jQuery
vue使用websocket的方法实例分析
Jun 22 Javascript
使用layer弹窗提交表单时判断表单是否输入为空的例子
Sep 26 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
实用的PHP带公钥加密类分享(每次加密结果都不一样哦)
2014/08/20 PHP
php结合web uploader插件实现分片上传文件
2016/05/10 PHP
php实现给二维数组中所有一维数组添加值的方法
2017/02/04 PHP
PHP自定义函数实现数组比较功能示例
2017/10/19 PHP
php时间戳转换代码详解
2019/08/04 PHP
javascript利用初始化数据装配模版的实现代码
2010/11/17 Javascript
解析offsetHeight,clientHeight,scrollHeight之间的区别
2013/11/20 Javascript
Web Uploader文件上传插件使用详解
2016/05/10 Javascript
浅析Nodejs npm常用命令
2016/06/14 NodeJs
AngularJS深入探讨scope,继承结构,事件系统和生命周期
2016/11/02 Javascript
JS实现自动阅读单词(有道单词本添加功能)
2016/11/14 Javascript
详解Vue单元测试case写法
2018/05/24 Javascript
layui 富文本赋值,取值,取纯文本值的实例
2019/09/18 Javascript
vue实现多级菜单效果
2019/10/19 Javascript
js 执行上下文和作用域的相关总结
2021/02/08 Javascript
[48:31]DOTA2-DPC中国联赛 正赛 Dynasty vs XG BO3 第一场 2月2日
2021/03/11 DOTA
python实现解数独程序代码
2017/04/12 Python
简单学习Python多进程Multiprocessing
2017/08/29 Python
python 矩阵增加一行或一列的实例
2018/04/04 Python
对python中矩阵相加函数sum()的使用详解
2019/01/28 Python
详解Python字典的操作
2019/03/04 Python
Python之pymysql的使用小结
2019/07/01 Python
python之pymysql模块简单应用示例代码
2019/12/16 Python
使用Python内置模块与函数进行不同进制的数的转换
2020/04/26 Python
python3.6.5基于kerberos认证的hive和hdfs连接调用方式
2020/06/06 Python
pandas创建DataFrame的7种方法小结
2020/06/14 Python
使用pandas读取表格数据并进行单行数据拼接的详细教程
2021/03/03 Python
amazeui页面分析之登录页面的示例代码
2020/08/25 HTML / CSS
荷兰最大的多品牌男装连锁店:Adam Brandstore
2019/12/31 全球购物
初中地理教学反思
2014/01/11 职场文书
思想品德课教学反思
2014/02/10 职场文书
大学生志愿者活动总结
2014/06/27 职场文书
师德师风事迹材料
2014/12/20 职场文书
2015年度质量工作总结报告
2015/04/27 职场文书
2015国庆节66周年标语
2015/07/30 职场文书
安全教育主题班会教案
2015/08/12 职场文书