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>
相关推荐
爱勇宝12 小时前
2026一人公司生存指南:用AI大模型,90天跑出你的第一条现金流
前端·后端·架构
fe小陈12 小时前
简单高效的状态管理方案:Hox + ahooks
前端
我叫黑大帅12 小时前
Vue3和Uniapp的爱恨情仇:小白也能懂的跨端秘籍
前端·javascript·vue.js
Panzer_Jack12 小时前
如何用 WebGL 去实现一个选取色彩背景图片透明化小工具 - Pick Alpha
前端·webgl
GIS之路12 小时前
ArcGIS Pro 中的 Python 入门
前端
树獭非懒12 小时前
告别繁琐多端开发:DivKit 带你玩转 Server-Driven UI!
android·前端·人工智能
偷油师傅13 小时前
拆解 OpenClaw - 05:13 个省 Token 的设计
架构
兆子龙13 小时前
当「多应用共享组件」成了刚需:我们从需求到模块联邦的落地小史
前端·架构
Qinana13 小时前
从代码到智能体:MCP 协议如何重塑 AI Agent 的边界
前端·javascript·mcp
Wect13 小时前
LeetCode 130. 被围绕的区域:两种解法详解(BFS/DFS)
前端·算法·typescript