RBAC前端架构-02:集成Vue Router、Vuex和Axios实现基本认证实现

1-引入router基本逻辑

  1. 新增frontend-vue2\src\router\index.js:
js 复制代码
import Vue from "vue";
import Router from "vue-router";

// 引入我们要展示的页面组件(先建两个示例页面)
import Login from "@/views/Login.vue";
import Dashboard from "@/views/Dashboard.vue";

// 告诉 Vue 使用 vue-router
Vue.use(Router);

// 路由表:定义页面路径与对应组件
const routes = [
    {
        path: "/login",
        name: "Login",
        component: Login,
    },
    {
        path: "/",
        name: "Dashboard",
        component: Dashboard,
        meta: { requiresAuth: true }, // meta 信息,用来标记需要登录才能访问
    },
];

// 创建 Router 实例
const router = new Router({
    mode: "history", // 使用 history 模式,URL 没有 #,更好看
    routes,
});

// 全局路由守卫:每次路由跳转都会执行
// to:跳转的目标信息
// from:跳转前的信息
// next:放行
router.beforeEach((to, from, next) => {
    // 判断目标路由是否需要登录
    const requiresAuth = to.matched.some((record) => record.meta.requiresAuth);

    // 这里先写死一个假登录状态,下一步我们再用 Vuex 来判断
    const isLoggedIn = false; // TODO: 下一步会替换成从 Vuex 读取 token

    if (requiresAuth && !isLoggedIn) {
        // 没登录想访问受保护页面,跳转到 /login
        console.log("目标页面" + to.fullPath + "需要登录");
        next({ path: "/login", query: { redirect: to.fullPath } });
    } else {
        // 其他情况直接放行
        next();
    }
});

export default router;
  1. 主页面引入路由标签:<router-view></router-view>
html 复制代码
<template>
    <div id="app">
        <router-view></router-view>
    </div>
</template>
  1. 修改frontend-vue2\src\main.js
js 复制代码
import Vue from "vue";
import App from "./App.vue";
// 路由组件
import router from "./router";

Vue.config.productionTip = false;

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

作用:

  1. 实现了基础的页面路由管理
  2. 建立全局路由守卫,没有token的就跳登录,简单权限控制
  3. 为后续集成Vuex管理用户登录状态预留了扩展点

2-引入Vuex基本逻辑

  1. 新增frontend-vue2\src\store\index.js,PS:login action后续修改为接口调用
js 复制代码
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
    state: {
        // 全局状态:存储用户 token
        token: null,
    },
    // mutations:修改state的唯一入口
    mutations: {
        // 设置 token(登录时调用)
        setToken(state, token) {
            state.token = token;
        },
        // 清除 token(退出时调用)
        clearToken(state) {
            state.token = null;
        },
    },
    // actions:处理异步逻辑
    actions: {
        // 登录:这里模拟一个接口调用
        login({ commit }, { username, password }) {
            return new Promise((resolve, reject) => {
                // 假装调了后端接口
                if (username === 'admin' && password === '123456') {
                    const fakeToken = 'fake-jwt-token'
                    commit('setToken', fakeToken) // 调用 mutation 修改 state
                    resolve(fakeToken)
                } else {
                    reject(new Error('用户名或密码错误'))
                }
            })
        },
        // 退出登录
        logout({ commit }) {
            commit("clearToken");
        },
    },
    // getters:数据的派生计算
    getters: {
        // 获取登录状态:是否有 token
        isLoggedIn: (state) => !!state.token,
    },
});
  1. 修改上方的frontend-vue2\src\router\index.js代码,新增Vuex支持:
js 复制代码
import Vue from "vue";
import Router from "vue-router";
import store from "@/store"; // 引入 Vuex

// 引入我们要展示的页面组件(先建两个示例页面)
import Login from "@/views/Login.vue";
import Dashboard from "@/views/Dashboard.vue";

// 告诉 Vue 使用 vue-router
Vue.use(Router);

// 路由表:定义页面路径与对应组件
const routes = [
    {
        path: "/login",
        name: "Login",
        component: Login,
    },
    {
        path: "/",
        name: "Dashboard",
        component: Dashboard,
        meta: { requiresAuth: true }, // meta 信息,用来标记需要登录才能访问
    },
];

// 创建 Router 实例
const router = new Router({
    mode: "history", // 使用 history 模式,URL 没有 #,更好看
    routes,
});

// 全局路由守卫:每次路由跳转都会执行
// to:跳转的目标信息
// from:跳转前的信息
// next:放行
router.beforeEach((to, from, next) => {
    // 判断目标路由是否需要登录
    const requiresAuth = to.matched.some((record) => record.meta.requiresAuth);

    // 登录状态:从Vuex 获取是否有token来判断
    const isLoggedIn = store.getters.isLoggedIn;

    if (requiresAuth && !isLoggedIn) {
        // 没登录想访问受保护页面,跳转到 /login
        console.log("目标页面" + to.fullPath + "需要登录");
        next({ path: "/login", query: { redirect: to.fullPath } });
    } else {
        // 其他情况直接放行
        next();
    }
});

export default router;
  1. 修改frontend-vue2\src\main.js
js 复制代码
import Vue from "vue";
import App from "./App.vue";
// 路由组件
import router from "./router";
// Vuex
import store from "./store";

Vue.config.productionTip = false;

new Vue({
    router,// router
    store, // 把 store 注入全局
    render: (h) => h(App),
}).$mount("#app");

作用:

  1. 使用Vuex存储全局状态
  2. 调用login action,验证成功后自动更新token并标记为已登录
  3. 调用logout action,清除token并标记为未登录
  4. 通过getters.isLoggedIn可以随时获取当前登录状态

3-引入axios基本逻辑

  1. 新增frontend-vue2\src\api\auth.js
js 复制代码
import request from "./request";

// 登录接口
export function loginApi(data) {
    return request({
        url: "/login",
        method: "post",
        data,
    });
}

// 获取当前用户信息
export function getUserInfo() {
    return request({
        url: "/user/info",
        method: "get",
    });
}
  1. 新增frontend-vue2\src\api\request.js
js 复制代码
// axios 封装
import axios from "axios";
import store from "@/store";
import router from "@/router";

// 创建 axios 实例
const service = axios.create({
    baseURL: "http://localhost:8080/api", // 后端接口的统一前缀
    timeout: 5000, // 请求超时时间
});

// 请求拦截器:每次请求都带上 token
service.interceptors.request.use(
    (config) => {
        const token = store.state.token;
        if (token) {
            config.headers["Authorization"] = `Bearer ${token}`;
        }
        return config;
    },
    (error) => {
        return Promise.reject(error);
    }
);

// 响应拦截器:统一处理错误
service.interceptors.response.use(
    (response) => {
        return response.data;
    },
    (error) => {
        if (error.response && error.response.status === 401) {
            // 401 未授权,说明 token 过期或无效
            store.dispatch("logout");
            router.push("/login");
        }
        return Promise.reject(error);
    }
);

export default service;
  1. 修改上方的frontend-vue2\src\store\index.js代码,将login action部分改为axios接口访问
js 复制代码
import Vue from "vue";
import Vuex from "vuex";
import { loginApi } from "@/api/auth";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    // 全局状态:存储用户 token
    token: null,
  },
  // mutations:修改state的唯一入口
  mutations: {
    // 设置 token(登录时调用)
    setToken(state, token) {
      state.token = token;
    },
    // 清除 token(退出时调用)
    clearToken(state) {
      state.token = null;
    },
  },
  // actions:处理异步逻辑(像 Java Service 层)
  actions: {
    async login({ commit }, { username, password }) {
      try {
        const res = await loginApi({ username, password });
        commit("setToken", res.token); // 后端返回的 token
      } catch (err) {
        throw err;
      }
    },
    // 退出登录
    logout({ commit }) {
      commit("clearToken");
    },
  },
  // getters:数据的派生计算
  getters: {
    // 获取登录状态:是否有 token
    isLoggedIn: (state) => !!state.token,
  },
});

作用:

  1. 使用axios实现接口访问
  2. 请求拦截器:在每次请求发送前,从 Vuex 的 store.state.token 中获取 token,添加进Authorization请求头
  3. 响应拦截器:对响应数据进行统一处理

4-页面代码补充

frontend-vue2\src\views\Dashboard.vue

html 复制代码
<template>
  <div class="dashboard">
    <h2>欢迎来到首页</h2>
    <p>这是登录后才能访问的页面</p>
    <button @click="logout">退出登录</button>
  </div>
</template>

<script>
export default {
  name: "Dashboard",
  methods: {
    logout() {
      this.$store.dispatch('logout')
      this.$router.push('/login')
    }
  }
}
</script>

frontend-vue2\src\views\Login.vue

html 复制代码
<template>
  <div class="login">
    <h2>登录页面</h2>
    <form @submit.prevent="handleLogin">
      <div>
        <label>用户名:</label>
        <input v-model="username" />
      </div>
      <div>
        <label>密码:</label>
        <input type="password" v-model="password" />
      </div>
      <button type="submit">登录</button>
    </form>
    <p v-if="errorMsg" style="color: red">{{ errorMsg }}</p>
  </div>
</template>

<script>
export default {
  name: "Login",
  data() {
    return {
      username: "",
      password: "",
      errorMsg: "",
    };
  },
  methods: {
    async handleLogin() {
      try {
        // 调用 Vuex 的 login action
        await this.$store.dispatch("login", {
          username: this.username,
          password: this.password,
        });
        // 登录成功后跳转到首页
        this.$router.push("/");
      } catch (err) {
        this.errorMsg = err.message;
      }
    },
  },
};
</script>
相关推荐
Tadas-Gao9 小时前
深度学习与机器学习的知识路径:从必要基石到独立范式
人工智能·深度学习·机器学习·架构·大模型·llm
晓得迷路了9 小时前
栗子前端技术周刊第 116 期 - 2025 JS 状态调查结果、Babel 7.29.0、Vue Router 5...
前端·javascript·vue.js
淡忘_cx9 小时前
使用Jenkins自动化部署vue项目(2.528.2版本)
vue.js·自动化·jenkins
顾北129 小时前
AI对话应用接口开发全解析:同步接口+SSE流式+智能体+前端对接
前端·人工智能
iDao技术魔方9 小时前
深入Vue 3响应式系统:为什么嵌套对象修改后界面不更新?
javascript·vue.js·ecmascript
摸鱼的春哥9 小时前
春哥的Agent通关秘籍07:5分钟实现文件归类助手【实战】
前端·javascript·后端
啊森要自信9 小时前
CANN ops-cv:揭秘视觉算子的硬件感知优化与内存高效利用设计精髓
人工智能·深度学习·架构·transformer·cann
国强_dev9 小时前
轻量级实时数仓架构选型指南
架构
念念不忘 必有回响9 小时前
viepress:vue组件展示和源码功能
前端·javascript·vue.js