JWT 3:为什么 Token 要放进 Authorization?Axios 拦截器到底解决了什么?

上一篇我们已经解决了 Token 的产生和验证。

现在又出现了一个现实问题:

如果我们的项目有 20 个接口,是不是每次都要手动写:

js 复制代码
headers: {
  Authorization: `Bearer ${token}`
}

当然不是。

所以这篇来理解 Axios 的请求拦截器。


一、先看一个非常麻烦的写法

假设现在有三个 API:

js 复制代码
axios.get('/repo', {
  headers: {
    Authorization: `Bearer ${token}`
  }
})
js 复制代码
axios.get('/user', {
  headers: {
    Authorization: `Bearer ${token}`
  }
})
js 复制代码
axios.post('/order', data, {
  headers: {
    Authorization: `Bearer ${token}`
  }
})

你会发现:

每个请求都在重复处理 Token。

而 Token 本来就是整个登录系统的公共逻辑。

所以应该把它统一处理。


二、我们需要一个"请求前统一处理"的地方

我们之前已经创建了:

text 复制代码
src/api/config.js

现在它不只是负责:

js 复制代码
baseURL
timeout

还负责:

在请求发出去之前,把 Token 自动放进 Header。

Axios 提供的就是:

js 复制代码
interceptors.request

也就是:

请求拦截器。


三、添加请求拦截器

修改:

text 复制代码
src/api/config.js

代码:

js 复制代码
import axios from 'axios';

const instance = axios.create({
  baseURL: '/api',
  timeout: 5000
});

instance.interceptors.request.use(config => {
  const token = localStorage.getItem('token');

  if (token) {
    config.headers['Authorization'] = `Bearer ${token}`;
  }

  return config;
});

export default instance;

这里最关键的是:

js 复制代码
instance.interceptors.request.use(...)

可以理解成:

"以后凡是使用这个 Axios 实例发出的请求,都先让我检查一下。"


四、拦截器到底在什么时候执行?

假设页面调用:

js 复制代码
getRepo()

然后:

js 复制代码
axios.get('/repo')

请求不会直接飞出去。

而是先经过:

text 复制代码
页面调用 getRepo()
        ↓
repo.js 调用 axios.get()
        ↓
Axios 请求拦截器
        ↓
读取 localStorage 中的 Token
        ↓
添加 Authorization
        ↓
真正发送请求

所以拦截器最大的意义就是:

统一处理所有请求的公共逻辑。


五、为什么从 localStorage 里取 Token?

因为登录成功以后,我们要先把 Token 保存起来。

例如:

js 复制代码
localStorage.setItem('token', token);

以后:

js 复制代码
localStorage.getItem('token');

就能拿出来。

所以整个关系是:

text 复制代码
登录成功
    ↓
Token 保存到 localStorage
    ↓
发送任意 API 请求
    ↓
拦截器读取 Token
    ↓
添加 Authorization

六、为什么写成 Bearer?

最终我们希望 Header 是:

text 复制代码
Authorization: Bearer eyJ...

所以代码:

js 复制代码
config.headers['Authorization'] = `Bearer ${token}`;

注意这里的空格:

text 复制代码
Bearer + 空格 + Token

这就是标准的 Bearer Token 写法。

如果写成:

js 复制代码
`Bearer${token}`

就会变成:

text 复制代码
BearereyJ...

后端再按:

js 复制代码
authorization.startsWith('Bearer ')

检查时就会失败。


七、这样 API 层会变得非常干净

user.js

js 复制代码
import axios from './config';

export const login = async (data) => {
  const res = await axios.post('/login', data);
  return res.data;
}

repo.js

js 复制代码
import axios from './config';

export const getRepo = async () => {
  const res = await axios.get('/repo');
  return res.data;
}

你会发现:

这两个文件根本不需要关心 Token。

它们只需要表达:

"我要调用哪个接口。"

至于:

"有没有 Token?"
"Token 放到哪个 Header?"

这些事情统一交给 Axios。

这就是职责分离。


八、请求拦截器为什么很重要?

因为很多项目都会有一些"所有请求都要做"的事情:

text 复制代码
Token
统一 Header
请求日志
请求参数处理
Loading
统一错误处理

这些都不适合散落到业务代码里。

所以:

text 复制代码
业务代码
负责业务

拦截器
负责公共逻辑

这样项目会清晰很多。


九、服务器收到请求以后

现在浏览器发出去的请求类似:

text 复制代码
GET /api/repo

Authorization: Bearer eyJ...

Mock 后端:

js 复制代码
const authorization = req.headers?.authorization;

然后:

js 复制代码
const token = authorization.slice('Bearer '.length);

最后:

js 复制代码
jwt.verify(token, secret);

整个请求链已经完整了:

text 复制代码
页面调用 API
        ↓
Axios 请求拦截器自动添加 Token
        ↓
请求发送到 /api/repo
        ↓
Mock 读取 Authorization
        ↓
取出 Token
        ↓
jwt.verify()
        ↓
返回数据

下一篇要解决的就不是"服务器怎么验证",而是:

React 自己怎么知道当前用户有没有登录?

这就轮到 Zustand 出场了。

相关推荐
东风破_1 小时前
JWT 5:路由守卫是什么?把整个 JWT 登录鉴权流程串起来
前端·后端
东风破_1 小时前
JWT 2:HTTP 是无状态的,为什么登录成功后还要给 Token?
前端·后端
东风破_1 小时前
JWT 4:Zustand 到底解决了什么?为什么登录状态要放进 Store?
前端·后端
IT_陈寒1 小时前
Vite动态导入差点让我秃头,原来问题出在这
前端·人工智能·后端
白泽_hunter2 小时前
项目里最常见的 5 个 this 指向坑:从规则到实战彻底讲透
前端
宿6742 小时前
vue3-pinia
前端·vue.js
白泽_hunter2 小时前
搞懂 JS 数据类型:从 typeof 到手写完整类型判断,一张图理清
前端
唐青枫2 小时前
别只把大括号当作用域:Zig Block、标签块与控制流实战
后端
日光倾2 小时前
TypeScript 随手记 —— 1
前端·javascript·typescript