Vue+vue-router+路由守卫实现路由鉴权功能

路由鉴权功能是Vue+vue-router框架中常见的功能之一,也是前端安全性的一个重要方面。这里提供一个基于Vue+vue-router的路由鉴权实战

安装依赖
首先,在Vue项目中安装所需的依赖。安装Vue、vue-router以及axios等依赖,创建一个新的Vue实例。

npm install vue vue-router axios --save

设置路由和路由守卫
在路由设置中,我们将路由拆分为两类,需要进行鉴权的路由和不需要进行鉴权的路由。需要进行鉴权的路由需要在路由元信息中添加requiresAuth: true属性。

在我们设置路由时,需要引入路由守卫。这里我们使用router.beforeEach守卫,在进入每个路由之前进行鉴权验证。

// main.js

import Vue from 'vue';
import App from './App.vue';
import router from './router';

Vue.config.productionTip = false;

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) { // 判断该路由是否需要进行鉴权
    // 获取token
    const token = localStorage.getItem('token');
    if (!token) { // token不存在,则跳转到登录页
      next('/login');
    } else { // token存在,则进行下一步路由
      next();
    }
  } else {
    next(); // 不需要进行鉴权,直接进行下一步路由
  }
});

new Vue({
  router,
  render: h => h(App),
}).$mount('#app');

实现登录页

登录页中需要对用户的信息进行验证,并在验证通过后获取返回的token。这里我们使用axios库来发送登录请求。

<template>
  <div class="login-page">
    <h2>Login</h2>
    <div>
      <label>Username:</label>
      <input type="text" v-model="username">
    </div>
    <div>
      <label>Password:</label>
      <input type="password" v-model="password">
    </div>
    <button @click="login">Login</button>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      username: '',
      password: '',
    };
  },
  methods: {
    async login() {
      const { data } = await axios.post('/api/login', { username: this.username, password: this.password });
      localStorage.setItem('token', data.token); // 将token存入localStorage中
      this.$router.push('/');
    },
  },
};
</script>

<style scoped>
.login-page {
  width: 400px;
  margin: 0 auto;
  padding: 20px;
  background-color: #f8f8f8;
  border: 1px solid #ccc;
}
input {
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 4px;
  margin-bottom: 10px;
}
button {
  padding: 10px 20px;
  background-color: #007aff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>

设置需要鉴权的路由

在路由设置中,我们为需要鉴权的路由添加requiresAuth元信息。这里我们设定/profile路由需要进行权限验证。

// router.js

import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from './views/Home.vue';
import Login from './views/Login.vue';
import Profile from './views/Profile.vue';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    name: 'home',
    component: Home,
  },
  {
    path: '/login',
    name: 'login',
    component: Login,
  },
  {
    path: '/profile',
    name: 'profile',
    component: Profile,
    meta: {
      requiresAuth: true,
    },
  },
];

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes,
});

export default router;

实现需要鉴权的页面
最后,在需要鉴权的页面中,我们可以使用beforeRouteEnter守卫来在进入页面前获取用户信息。这里我们使用axios库获取用户信息。

<template>
  <div class="profile-page">
    <h2>Profile</h2>
    <div>
      <label>Username:</label>
      <span>{{ username }}</span>
    </div>
    <div>
      <label>Email:</label>
      <span>{{ email }}</span>
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      username: '',
      email: '',
    };
  },
  beforeRouteEnter(to, from, next) {
    axios.get('/api/userinfo').then(({ data }) => {
      next(vm => {
        vm.username = data.username;
        vm.email = data.email;
      });
    }).catch(() => {
      next('/');
    });
  },
};
</script>

<style scoped>
.profile-page {
  width: 400px;
  margin: 0 auto;
  padding: 20px;
  background-color: #f8f8f8;
  border: 1px solid #ccc;
}
label {
  font-weight: bold;
}
span {
  margin-left: 10px;
}
</style>

上述代码中,在进入页面之前,我们使用axios发送请求获取用户信息。如果获取失败,则跳转到首页。如果请求成功,则将用户信息存入Vue实例中,并使用next将其传递给组件。在组件中,我们可以直接使用username和email属性渲染页面。

完整的代码如下:

// main.js

import Vue from 'vue';
import App from './App.vue';
import router from './router';

Vue.config.productionTip = false;

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) { // 判断该路由是否需要进行鉴权
    // 获取token
    const token = localStorage.getItem('token');
    if (!token) { // token不存在,则跳转到登录页
      next('/login');
    } else { // token存在,则进行下一步路由
      next();
    }
  } else {
    next(); // 不需要进行鉴权,直接进行下一步路由
  }
});

new Vue({
  router,
  render: h => h(App),
}).$mount('#app');

// router.js

import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from './views/Home.vue';
import Login from './views/Login.vue';
import Profile from './views/Profile.vue';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    name: 'home',
    component: Home,
  },
  {
    path: '/login',
    name: 'login',
    component: Login,
  },
  {
    path: '/profile',
    name: 'profile',
    component: Profile,
    meta: {
      requiresAuth: true,
    },
  },
];

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes,
});

export default router;

// Login.vue

<template>
  <div class="login-page">
    <h2>Login</h2>
    <div>
      <label>Username:</label>
      <input type="text" v-model="username">
    </div>
    <div>
      <label>Password:</label>
      <input type="password" v-model="password">
    </div>
    <button @click="login">Login</button>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      username: '',
      password: '',
    };
  },
  methods: {
    async login() {
      const { data } = await axios.post('/api/login', { username: this.username, password: this.password });
      localStorage.setItem('token', data.token); // 将token存入localStorage中
      this.$router.push('/');
    },
  },
};
</script>

<style scoped>
.login-page {
  width: 400px;
  margin: 0 auto;
  padding: 20px;
  background-color: #f8f8f8;
  border: 1px solid #ccc;
}
input {
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 4px;
  margin-bottom: 10px;
}
button {
  padding: 10px 20px;
  background-color: #007aff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>

// Profile.vue

<template>
  <div class="profile-page">
    <h2>Profile</h2>
    <div>
      <label>Username:</label>
      <span>{{ username }}</span>
    </div>
    <div>
      <label>Email:</label>
      <span>{{ email }}</span>
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      username: '',
      email: '',
    };
  },
  beforeRouteEnter(to, from, next) {
    axios.get('/api/userinfo').then(({ data }) => {
      next(vm => {
        vm.username = data.username;
        vm.email = data.email;
      });
    }).catch(() => {
      next('/');
    });
  },
};
</script>

<style scoped>
.profile-page {
  width: 400px;
  margin: 0 auto;
  padding: 20px;
  background-color: #f8f8f8;
  border: 1px solid #ccc;
}
label {
  font-weight: bold;
}
span {
  margin-left: 10px;
}
</style>
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
为了实现动态路由和用户权限路由,我们需要进行以下步骤: 1. 安装依赖 ```shell npm install vue-router@4 pinia element-plus mock -S npm install @types/mock -D ``` 2. 创建路由配置文件 在src文件夹下创建router文件夹,并在其中创建index.ts文件,用于配置路由。在该文件中,我们需要定义路由的各个页面组件,并根据需要配置路由的子路由路由守卫。例如: ```typescript import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' import Home from '@/views/home/indexName.vue' import Login from '@/views/login/index.vue' import NotFound from '@/views/404/index.vue' const routes: Array<RouteRecordRaw> = [ { path: '/', name: 'Home', component: Home, meta: { title: '首页', requireAuth: true // 需要登录才能访问 } }, { path: '/login', name: 'Login', component: Login, meta: { title: '登录' } }, { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound, meta: { title: '404' } } ] const router = createRouter({ history: createWebHistory(), routes }) // 路由守卫 router.beforeEach((to, from, next) => { const token = localStorage.getItem('token') if (to.meta.requireAuth && !token) { next('/login') } else { next() } }) export default router ``` 3. 在main.ts中挂载路由 在main.ts中,我们需要将路由配置文件挂载到Vue实例中,以便在应用中使用路由。例如: ```typescript import { createApp } from 'vue' import App from './App.vue' import router from './router' createApp(App).use(router).mount('#app') ``` 4. 创建权限控制文件 在src文件夹下创建permission文件夹,并在其中创建index.ts文件,用于控制用户权限。在该文件中,我们需要定义用户的权限列表,并根据需要判断用户是否有权限访问某个路由。例如: ```typescript import router from '@/router' const whiteList = ['/login'] // 不需要登录即可访问的页面 router.beforeEach((to, from, next) => { const token = localStorage.getItem('token') if (token) { if (to.path === '/login') { next('/') } else { // 判断用户是否有权限访问该路由 const hasPermission = true // 根据实际情况判断用户是否有权限 if (hasPermission) { next() } else { next('/404') } } } else { if (whiteList.indexOf(to.path) !== -1) { next() } else { next('/login') } } }) ``` 5. 在App.vue中挂载路由渲染入口 在App.vue中,我们需要将路由渲染入口挂载到模板中,以便在应用中渲染路由。例如: ```html <template> <div id="app"> <router-view /> </div> </template> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一花一world

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值