标签:前端认证、JWT、Vue.js、登录页面、受保护路由、Axios、入门教程、项目实践
前言
欢迎来到"前后端与数据库交互详解"系列的第9篇文章!在前八篇文章中,我们从Vue.js前端基础,到Express后端API、MongoDB整合,再到JWT认证,构建了一个带安全登录的后端。现在,后端已保护,但前端还需处理:如何登录、存储JWT并安全调用API?
本篇文章的焦点是 前端认证整合,特别是用Vue.js处理JWT,实现登录页面和受保护路由。我们将解释前端认证流程、JWT存储,并在结尾扩展第七/八篇的项目:添加Vue登录组件、路由守卫,只有认证用户才能访问用户管理系统(CRUD界面)。这将形成一个完整的full-stack认证应用。未来,我们将引入状态管理。
前提:您已安装Vue CLI和Axios(从前文)。我们用Vue Router(第二篇)实现路由保护,localStorage存储JWT(简单入门;生产用更安全方式)。后端基于第八篇运行。
一、前端认证是什么?
前端认证是处理用户身份验证的客户端逻辑:发送登录请求、存储令牌,并在后续API调用中附加令牌。如果令牌无效,重定向到登录页。
-
为什么前端认证?
- 用户体验:无缝登录/注销,保护私有页面。
- 与后端协作:前端发送JWT,后端验证(第八篇)。
- JWT 在前端:存储在localStorage或cookie,Axios自动附加到header。
- 对比其他:Session需服务器状态;JWT无状态,适合SPA(如Vue)。
- 安全考虑:避免XSS,设置HttpOnly cookie(高级);我们用localStorage入门。
- 在Vue中的作用:用组件处理表单,路由守卫检查认证。
-
核心概念:
- 登录流程:POST /api/login,存储res.data.token。
- 拦截器:Axios.interceptors.request添加Authorization: Bearer 。
- 路由保护:Vue Router的beforeEach检查localStorage。
- 注销:清除存储,重定向。
- 错误处理:捕获401(未授权),跳转登录。
在我们的系列中,这是认证的最后一环:前后端完整闭环。
二、前端认证的基本使用
- 登录组件:表单v-model绑定,Axios.post发送。
- JWT存储:localStorage.setItem('token', token)。
- 请求拦截:Axios配置自动加header。
- 路由守卫:router.beforeEach((to, from, next) => { if (to.meta.requiresAuth && !token) next('/login'); })。
示例:登录后 localStorage.setItem('token', res.data.token); this.$router.push('/dashboard');。
接下来,通过项目实践这些。
三、实现完整项目:带前端认证的用户管理系统
项目目标:扩展第七篇的Vue前端和第八篇的Express后端,添加登录页面、JWT处理和路由保护。只有登录用户才能访问CRUD界面(用户列表/添加/编辑/删除)。这是一个独立的完整full-stack应用,可以运行前后端,测试认证流。
步骤 1: 前端准备(扩展Vue项目)
基于第七篇的Vue项目(user-manager-vue),安装Vue Router(如果未):vue add router。更新依赖:确保Axios安装。
步骤 2: 配置Axios拦截器和路由
在src/main.js中添加:
javascript
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import axios from 'axios';
// Axios 全局配置
axios.defaults.baseURL = 'http://localhost:3000/api'; // 后端API基础URL
// 请求拦截器:添加JWT
axios.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, error => Promise.reject(error));
// 响应拦截器:处理401
axios.interceptors.response.use(response => response, error => {
if (error.response.status === 401) {
localStorage.removeItem('token');
router.push('/login');
}
return Promise.reject(error);
});
Vue.config.productionTip = false;
new Vue({
router,
render: h => h(App)
}).$mount('#app');
在src/router/index.js中配置路由和守卫:
javascript
import Vue from 'vue';
import VueRouter from 'vue-router';
import Login from '../components/Login.vue'; // 新组件
import UserManager from '../components/UserManager.vue'; // 从第七篇
Vue.use(VueRouter);
const routes = [
{ path: '/', redirect: '/login' },
{ path: '/login', name: 'Login', component: Login },
{ path: '/users', name: 'Users', component: UserManager, meta: { requiresAuth: true } }
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
});
// 路由守卫
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token');
if (to.meta.requiresAuth && !token) {
next('/login');
} else {
next();
}
});
export default router;
步骤 3: 创建登录组件
新建src/components/Login.vue:
vue
<template>
<div>
<h1>登录</h1>
<form @submit.prevent="login">
<input v-model="username" placeholder="Username" required />
<input v-model="password" type="password" placeholder="Password" required />
<button type="submit">登录</button>
</form>
<p v-if="error">{{ error }}</p>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
username: '',
password: '',
error: ''
};
},
methods: {
async login() {
try {
const res = await axios.post('/login', { username: this.username, password: this.password });
localStorage.setItem('token', res.data.token);
this.$router.push('/users');
} catch (err) {
this.error = '登录失败:' + (err.response?.data?.error || '未知错误');
}
}
}
};
</script>
- 解释:POST到/api/login,存储token,重定向到/users(CRUD页面)。
更新第七篇的UserManager.vue:无需大改,但确保API调用用Axios(拦截器会自动加token)。
在App.vue中用<router-view />渲染路由。
步骤 4: 运行和测试
- 后端:运行第八篇的
node server.js(localhost:3000)。 - 前端:
npm run serve(localhost:8080)。 - 测试:访问/,重定向到/login;输入第八篇注册的凭证(e.g., username: "test", password: "123456"),登录后跳转到/users,CRUD操作成功(token附加);注销(可选添加按钮:localStorage.removeItem('token'); this.$router.push('/login'););无token访问/users,重定向登录。
- 这是一个完整的带认证full-stack应用!前后端协作,实现安全CRUD。
步骤 5: 扩展(可选)
- 注册页面:类似登录,POST /api/register。
- 自动续期:检查token过期,刷新。
- UI库:用Element UI美化表单。
四、常见问题与调试
- 401错误?检查token存储、拦截器;后端密钥匹配。
- 路由不跳转?验证守卫逻辑,console.log(token)。
- CORS?后端已启用(第八篇),但检查header。
- 安全?localStorage易XSS;生产用cookie或Vuex+secure storage。
总结
通过本篇,您学会了前端认证整合,用Vue.js处理JWT,实现登录和路由保护。带认证的用户管理系统证明了完整认证流,形成独立的full-stack项目。
下一篇文章:状态管理基础:Vuex 在 Vue.js 中的应用,实现全局用户状态。我们将用Vuex管理认证状态,提升应用可扩展性。如果有疑问,欢迎评论!
(系列导航:这是第9/20篇。关注我,跟着学完整系列!)