1. 开始之前的准备
我们先在新创建好的react空项目下进行配置环境,在终端输入:
pnpm i zustand
pnpm i vite-mock-plugin-mock //在 Vite 项目中模拟 API 接口的包
接着我们在 vite.config.js 文件中配置 Vite 插件,这是主要用于在 Vite 项目中启用 Mock 功能,方便在开发阶段模拟后端接口数据。
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react'; // 支持React项目的Vite插件
import { viteMockServe } from 'vite-plugin-mock'; // 用于模拟API请求的插件
import path from 'path'; // Node.js路径处理模块,用于解析文件路径
添加:
// 使用defineConfig函数定义Vite的配置
export default defineConfig({
// 配置Vite的插件
plugins: [
// 使用@vitejs/plugin-react插件,支持React项目
react(),
// 配置vite-plugin-mock插件
viteMockServe({
// 指定Mock数据文件的存放路径为src/mock目录
mockPath: 'src/mock',
// 在开发环境中启用Mock服务
localEnabled: true,
})
],
// 配置模块解析选项
resolve: {
// 配置路径别名
alias: {
// 将@映射到项目的src目录
'@': path.resolve(__dirname, 'src')
}
}
})
配置登录接口模拟(Mock)
随后我们在src下创建mock文件夹,放置文件login.js
// 导出一个包含模拟接口配置的数组
export default [
{
// 定义接口的URL路径,客户端需要访问此路径来触发该模拟接口
url: '/api/login',
// 指定接口的请求方法为POST,与客户端登录请求的方法保持一致
method: 'post',
// 设置模拟请求的延迟响应时间为2秒,用于测试前端的加载状态
timeout: 2000,
// 接口响应的处理函数,接收请求(req)和响应(res)对象作为参数
response: (req, res) => {
// 从请求体中解构提取用户名和密码字段
const {username, password} = req.body;
// 登录验证逻辑:检查用户名和密码是否同时符合预期
if (username !== 'admin' || password !== '123456') {
// 返回错误响应对象,包含错误码和错误信息
return {
code: 1, // 自定义错误码,表示登录失败
message: '用户名或密码错误' // 明确的错误提示信息
}
}
// 若验证通过(用户名和密码均正确),则返回成功响应
return {
username, // 返回客户端提交的用户名
password // 返回客户端提交的密码(实际应返回token等安全凭证)
}
}
}
]
使用 Apifox 发送请求
Apifox 可以方便地发起 HTTP、HTTPS 等多种协议的请求,设置请求头、请求体等参数,并查看响应结果,这和 Linux 下的curl命令功能类似 。curl是一个利用 URL 语法在命令行下工作的文件传输工具,也能用于发送各种 HTTP 请求(比如 GET、POST 等),并获取服务器返回的响应。
步骤如下:
(1. 创建项目:打开 Apifox,点击左侧搜索框旁边的 “+” 号按钮,创建一个新的项目。 这里我们直接选择默认创建好的"个人项目"。
(2. 新建接口:在项目中点击 “新建接口” 按钮,填写接口的基本信息。将接口名称设置为 “登录接口”,请求方法选择 “POST”,请求 URL 填写为 “/api/login”。
这里我们根据项目地址输入 http://localhost:5173/api/login
(3. 设置请求体:在接口的 “请求体” 部分,选择 Body 部分和 JSON 格式,同时设置请求体的结构,这里我们就用{"username":"admin","password":"123456"},表示需要传入用户名和密码。
(4. 发送请求:点击接口页面中的 “发送” 按钮,Apifox 会向设置的 “/api/login” 接口发送 POST 请求,并显示响应结果。你可以在响应区域查看返回的内容。
当接口请求的状态码为
200时,表示请求成功。其中响应时间为 2.02 s,数据大小为 40 B。
响应的 Body 内容也是 JSON 格式,返回了 username 和 password 字段,与请求中的字段值一致。
此时说明我们刚刚配置的模拟接口已经成功工作,能够正确接收请求并返回相应的数据。
2. 实现基于 JSON Web Token (JWT) 的身份认证机制
我们先安装 jsonwebtoken 库,以便在项目中使用 JWT 功能。
pnpm i jsonwebtoken
再来到login.js中添加:
// 从 jsonwebtoken 库中导入 sign 函数,用于生成 JWT
import jwt from 'jsonwebtoken';
// 解构赋值获取 sign 函数,用于生成 JWT 令牌
const { sign } = jwt;
// 安全密钥,用于签署 JWT 令牌
const secret = '!&124coddefgg';
// 调用 sign 函数生成 JWT 令牌
const token = jwt.sign(
{
// 存储在 JWT 中的用户信息(Payload 部分)
user: {
id: "001", // 用户唯一标识
username: "admin" // 用户名
}
},
secret, // 用于签名的密钥(应从环境变量获取)
{
expiresIn: 86400 // 令牌有效期(单位:秒),此处为 24 小时
}
// 返回包含令牌的对象(可扩展其他属性)
return {
token, // 生成的 JWT 令牌
...
};
};
此时我们返回 apifox 生成 token :
在请求头中添加身份验证信息,用于验证客户端是否有权限访问该接口
{
url: '/api/user',
method: 'get',
response: (req, res) => {
// 用户端 token headers
const token = req.headers["authorization"].split(' ')[1];
console.log(token)
try {
const decode = jwt.decode(token, secret);
console.log(decode)
return {
code: 0,
data: decode.user
}
} catch(err) {
return {
code: 1,
message: 'Invalid token'
}
}
}
}
在 src/api 目录下创建两个核心文件来共同构成项目的API请求系统
先安装axios
pnpm i axios
config.js
// 导入 axios HTTP 客户端库
import axios from 'axios';
axios.defaults.baseURL = 'http://localhost:5177/api';
// 请求拦截器:在每个请求发送前执行用于自动添加 JWT 令牌到请求头,实现身份验证
axios.interceptors.request.use(config => {
// 从本地存储中获取用户令牌(如果存在)
const token = localStorage.getItem('token') || "";
// 如果令牌存在,则添加到请求头的 Authorization 字段
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// 响应拦截器:在每个响应返回后执行
axios.interceptors.response.use(res => {
// 打印响应标识(实际项目中可移除或改为更详细的日志)
console.log('|||||||');
// 直接返回响应数据,不做其他处理
return res;
});
// 导出配置好的 axios 实例供项目使用
export default axios;
这段代码配置了 Axios HTTP 客户端的全局设置和拦截器,使得项目中所有 API 请求都会自动携带身份令牌,同时便于统一处理响应。
user.js
import axios from './config';
export const getUser = () => {
return axios.get('/user');
}
export const doLogin = (data) => {
return axios.post('/login', data);
}
在这里代码封装了两个与用户认证相关的 API 请求函数:
getUser():调用已配置好的 axios 实例发送 GET 请求到/user接口,由于 axios 配置了请求拦截器,会自动携带本地存储中的 JWT 令牌,用于获取当前登录用户的详细信息。doLogin(data):调用 axios 发送 POST 请求到/login接口,接收表单数据(如用户名 / 密码)作为参数并传递给后端,用于用户登录认证,成功后通常会返回新的 JWT 令牌。
发送 GET 请求
当出现 code: 0时,表示请求成功。
你大概率会注意到 token 前面的 Bearer ,它是什么?
持有者(Bearer) :这里指持有令牌的客户端(如浏览器、APP)。服务器通过验证令牌的有效性,确认 “持有者” 是否有权限访问资源。
整个过程简单概括就是:用 secret 密钥签名生成的 JWT 令牌,会以 Bearer ${token} 的格式,通过 HTTP 请求头的 Authorization 字段,从客户端(持有者)传递到服务器,用于身份验证。
小结
在整个流程中,我们通过环境搭建→模拟接口→JWT生成→请求拦截→身份验证五步骤,确保前端能安全访问受保护的资源。
-
环境准备 :用pnpm安装zustand、vite-mock-plugin-mock(模拟API)、jsonwebtoken(生成JWT)和axios(HTTP请求)等依赖。
-
Vite配置 :在vite.config.js中启用React插件和Mock服务,设置Mock数据路径为src/mock,并配置@别名指向src目录。
-
Mock接口 :在src/mock/login.js中定义登录接口,模拟用户验证逻辑(用户名admin/密码123456),成功后生成JWT令牌(包含用户信息,有效期24小时)。
-
API系统 :在src/api/config.js中配置Axios拦截器(自动添加JWT到请求头),并在user.js中封装登录和获取用户信息的API函数。
-
测试验证 :用Apifox工具测试登录接口获取JWT,再测试带令牌的GET请求,验证身份认证机制正常工作。
在下篇文章中,我们将利用 zustand , 单页面SPA , 受控组件,懒加载等相关技术搭建一个简单的用户登录支付的 React 项目。