vue-router结合vuex实现用户权限控制功能


Posted in Javascript onNovember 14, 2019

为了实现前端校验用户,后端需要在用户登录的时候记录下该用户的状态并加密之后返回给前端。之后该用户的所有请求都应该附带这个加密后的状态,后端取到这个状态解密,并与之前保存的状态对比,以此来判断该用户是否登录或合法。

我这里使用了node简单了写了个本地的express服务,来实现上述功能。完整的代码直接贴出来:

// server.js
const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const app = express();
// secret是后端加密的密钥
const secret = 'rhwl';
app.use((req, res, next) => {
 res.header('Access-Control-Allow-Origin', '*');
 res.header('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS,POST,PUT');
 res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
 if (req.method.toLowerCase() === 'options') {
  return res.end();
 }
 next();
});
app.use(bodyParser.json());
app.post('/login', (req, res) => {
 const { username } = req.body;
 if (username === 'admin') { // 如果是合法用户,使用jwt进行加密生成token
  res.json({
   code: 0,
   username: 'admin',
   token: jwt.sign({ username: 'admin' }, secret, {
    expiresIn: 20,
   }),
  });
 } else {
  res.json({
   code: 1,
   data: '用户名不存在',
  });
 }
});
app.get('/validate', (req, res) => {
 const token = req.headers.authorization; // 在请求头中附带token信息
 jwt.verify(token, secret, (err, decode) => { // 验证token是否合法
  if (err) {
   return res.json({
    code: 1,
    data: '当前token无效',
   });
  }
  // 如果验证合法,重新生成新的token,并返回信息
  res.json({
   username: decode.username,
   code: 0,
   token: jwt.sign({ username: 'admin' }, secret, {
    expiresIn: 20,
   }),
  });
 });
});
app.listen(3000, ()=>{
  console.log('服务器在3000端口运行');
});

2.项目中axios封装

然后我们在项目中封装符合自己需求的ajax请求,现在通常都是基于axios库。在自己封装的ajax插件中,要在每次的请求头中添加上token。代码实现:

// ajaxResquest.js
import axios from 'axios';
class ajaxResquest {
  constructor(){
    // 根据当前模式自动切换baseURL
    this.baseURL = process.env.NODE_ENV === 'development' ? 'http://localhost:3000' : '/';
    this.timeout = 5000; // 设置请求超时为5s
  }
  request(config){
    const instance = axios.create({
      baseURL: this.baseURL,
      timeout: this.timeout,
    });
    instance.interceptor.request.use((config) => {
      // 将保存在本地的token添加到每次请求的请求头中
      // 这样就可以实现在请求时顺带附加用户的校验信息的需求
      config.headers.Authorization = localStorage.getItem('token');
      return config;
    }, (err) => {
      return Promise.reject(err);
    });
    instance.interceptor.response.use((req,res) => {
      return req.data;
    }, (err) => {
      Promise.reject(err);
    });
    // 将使用request时候需要的参数也添加到instance中
    return instance(config);
  }
}
export default new ajaxRequest();

然后统一管理项目api接口:

// api.js
import ajax from 'ajaxResquest';
export const userLogin = (username) => ajax.request({url: '/login', method: 'POST', data: {
  username,
}});
export const userValidate = () => ajax.request({url: '/validate'});

接下来我们在项目中具体实现用户登陆和权限校验的需求。

3.vuex记录用户登录

先将登陆组件配合vuex使用来触发用户登陆的行为,并且将用户登录之后的信息保存在vuex中,登陆组件的代码:

// userLogin component
<template>
  <div>
    <el-input style="width:200px" v-model="username"></el-input>
    <el-button @click="login">登录</el-button>
  </div>
</template>
<script>
export default {
  data(){
    return {
      username: '',
    }
  },
  methods: {
    login(){
      // 这里触发vuex中的actions,在vuex中调用用户登陆接口
      // 从而将用户登陆之后的状态保存至vuex中
      this.$store.dispatch('login', this.username).then((data) => {
        // 登陆成功之后,路由跳转至用户账户页或者进行你需要的操作
        this.$router.push('/profile');
      });
    }
  }
}
</script>

接着是vuex的store.js

// store.js
import Vue from 'vue';
import Vuex from 'vuex';
import {userLogin, userValidate} from 'api.js';
Vue.use(Vuex);
export default Vuex.store({
  state: {
    username: '', 
  },
  mutations: {
    setUsername(state, username){
      state.username = username;
    }
  },
  actions: {
    async login({commit}, username){
      const res = await userLogin(username);
      if (res.code === 1) { // 登录失败
        return Promise.reject(res);
      }
      // 登录成功后将接口返回的token保存在本地
      localStorage.setItem('token', res.token);
      // 将用户名保存在vuex中
      commit('setUsername', username);
    }
  }
});

经过上面的操作,我们将用户登录中调用登录接口的操作通过vuex实现,将成功登录后的用户名保存在vuex中,此时的token保存在浏览器本地。但是vuex中的数据并不是持久数据,刷新之后保存的用户名就会消失,接下来我们实现刷新页面或者路由跳转时进行用户校验,如果验证通过则会生成新的token和username并保存。

4.vuex配合vue-router实现登录校验

当用户刷新页面时,或者点击其他页面切换路由router时,需要调用后端的validate接口,该接口通过验证已保存的token校验当前用户是否合法。我们在vuex的store.js中添加以下代码:

export default Vuex.store({
  state: {
    username: '',
  },
  mutations: {
    setUsername(state, username){
      state.username = username;
    } 
  },
  actions: {
    async login({commit}, username){
      ...
    },
    async validate({commit}) {
      // 调用userValidate时,会将
      const res = await userValidate();
      if (res.code === 1) { // 此时用户校验失败
        return Promise.reject(res);
      }
      // 如果校验成功,重新保存token和username 
      localStorage.setItem('token', res.token);
      commit('setUsername', res.username);
    }
  }
});

基本上我们通过上面的代码就实现了用户权限控制所需要的所有前提操作:

  • 用户成功登陆在本地保存token
  • 在自己封装的ajax的请求头部添加保存的token信息
  • 后端服务提供对前端token的校验能力

那么接下来就就是路由router刷新或改变的时候如何进行权限控制了。

5.vue-router钩子实现用户权限控制

使用过vue-router的同学们都知道,路有也是有钩子函数的,在官方文档里面被称为 导航守卫 。导航守卫允许我们可以精准的在每个路由变化的时候进行操作,我们就这里判断用户权限。在vue项目的的main.js中修改:

import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// 在这里使用路由的导航守卫进行权限控制
// 可以自定义不需要校验用户的路由白名单
const whiteList = ['/'];
router.beforeEach(async (to, from, next) => {
  // 要去的页面是白名单,直接跳转
  if (whiteList.includes(to.path)) {
    next();
  }
  // 不是白名单,调用vuex中的validate行为
  const flag = await store.dispatch('validate');
  if (flag) { // 用户校验通过,直接跳转
    next();
  } else { // 用户校验失败
    next('/login'); // 跳转至用户登陆页
    // 顺带说一下,这里还可以在router中的meta属性中添加isNeeded: true/false
    // 然后配合这个属性更加精细的控制未通过用户校验时的页面是否允许跳转
  }
});
// vuex
Vue.use(ElementUI);
Vue.config.productionTip = false;
new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app');

总结

以上所述是小编给大家介绍的vue-router结合vuex实现用户权限控制,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
javascript 自动填写表单的实现方法
Apr 09 Javascript
ExtJS4 组件化编程,动态加载,面向对象,Direct
May 12 Javascript
Prototype源码浅析 Enumerable部分之each方法
Jan 16 Javascript
file模式访问网页时iframe高度自适应解决方案
Jan 16 Javascript
随窗体滑动的小插件sticky源码
Jun 21 Javascript
jQuery中get()方法用法实例
Dec 27 Javascript
javascript跑马灯抽奖实例讲解
Apr 17 Javascript
微信小程序 Buffer缓冲区的详解
Jul 06 Javascript
Vue文件配置全局变量的实例
Sep 06 Javascript
微信小程序实现的一键复制功能示例
Apr 24 Javascript
vue项目打包后怎样优雅的解决跨域
May 26 Javascript
vue中控制mock在开发环境使用,在生产环境禁用方式
Apr 06 Vue.js
vue router 传参获取不到的解决方式
Nov 13 #Javascript
Vue解析带html标签的字符串为dom的实例
Nov 13 #Javascript
vue props对象validator自定义函数实例
Nov 13 #Javascript
微信小程序获取当前位置和城市名
Nov 13 #Javascript
使用Promise封装小程序wx.request的实现方法
Nov 13 #Javascript
微信小程序wx.request的简单封装
Nov 13 #Javascript
vue使用prop可以渲染但是打印台报错的解决方式
Nov 13 #Javascript
You might like
分页详解 从此分页无忧(PHP+mysql)
2007/11/23 PHP
简单的JS多重继承示例
2008/03/13 Javascript
ASP.NET jQuery 实例9  通过控件hyperlink实现返回顶部效果
2012/02/03 Javascript
jquery动画3.创建一个带遮罩效果的图片走廊
2012/08/24 Javascript
JS页面延迟执行一些方法(整理)
2013/11/11 Javascript
Extjs的FileUploadField文件上传出现了两个上传按钮
2014/04/29 Javascript
jQuery中scrollLeft()方法用法实例
2015/01/16 Javascript
JavaScript将当前时间转换成UTC标准时间的方法
2015/04/06 Javascript
浅谈被jQuery抛弃的函数及替代函数
2015/05/03 Javascript
Bootstrap栅格系统简单实现代码
2017/03/06 Javascript
discuz表情的JS提取方法分析
2017/03/22 Javascript
学习使用Bootstrap页面排版样式
2017/05/11 Javascript
获取本机IP地址的实例(JavaScript / Node.js)
2017/11/24 Javascript
vue框架搭建之axios使用教程
2018/07/11 Javascript
前端防止用户重复提交js实现代码示例
2018/09/07 Javascript
JS实现动态添加外部js、css到head标签的方法
2019/06/05 Javascript
基于Bootstrap和JQuery实现动态打开和关闭tab页的实例代码
2019/06/10 jQuery
Vue快速实现通用表单验证的示例代码
2020/01/09 Javascript
JavaScript链式调用原理与实现方法详解
2020/05/16 Javascript
[01:07]DOTA2次级职业联赛 - Fpb战队宣传片
2014/12/01 DOTA
kNN算法python实现和简单数字识别的方法
2014/11/18 Python
浅谈关于Python3中venv虚拟环境
2018/08/01 Python
解决pycharm的Python console不能调试当前程序的问题
2019/01/20 Python
python3 实现的对象与json相互转换操作示例
2019/08/17 Python
python编程进阶之异常处理用法实例分析
2020/02/21 Python
深入浅析Python 函数注解与匿名函数
2020/02/24 Python
Python爬虫之Spider类用法简单介绍
2020/08/04 Python
来自南加州灵感的工作和娱乐服装:TravisMathew
2019/05/01 全球购物
幼儿园教师自我鉴定
2014/03/20 职场文书
体育课课后反思
2014/04/24 职场文书
建筑节能汇报材料
2014/08/22 职场文书
工伤私了协议书范本
2014/11/24 职场文书
三八妇女节慰问信
2015/02/14 职场文书
2015年中学校长工作总结
2015/05/19 职场文书
总结Pyinstaller打包的高级用法
2021/06/28 Python
解决IDEA翻译插件Translation报错更新TTK失败不能使用
2022/04/24 Python