发布时间:2026/9/5 20:21:16
axios 请求鉴权实战指南:Bearer Token、HTTP Basic、API Key 与 Cookie 会话方案 axios 请求鉴权实战指南Bearer Token、HTTP Basic、API Key 与 Cookie 会话方案【免费下载链接】axiosPromise based HTTP client for the browser and node.js项目地址: https://gitcode.com/GitHub_Trending/ax/axios绝大多数 API 都需要某种形式的鉴权机制。本文围绕 axios 官方文档中的认证Authentication专题系统讲解四种主流鉴权方案——Bearer TokenJWT、HTTP Basic、API Key 与基于 Cookie 的会话认证——各自的配置写法与推荐用法并结合 axios 仓库源码深入剖析auth配置项在不同适配器fetch、http、xhr下的真实处理链路帮助你在实际项目中做出正确、安全且可维护的鉴权决策。鉴权方式总览在展开细节之前先给出 axios 对四类常见鉴权方案的支持方式方便快速定位鉴权方案axios 配置方式底层机制典型场景Bearer TokenJWT请求拦截器中设置Authorization请求头自定义请求头每请求动态取值前后端分离、OAuth2 / JWT 服务HTTP Basicauth: { username, password }选项axios 自动编码并写入Authorization: Basic ...内网 API、简单服务账号API Key实例默认请求头或params查询参数普通请求头 / URL 参数第三方开放平台Cookie / 会话withCredentials: true浏览器自动携带同源/跨域 Cookie同域站点会话、SSO核心原则官方文档明确提示auth选项只用于 HTTP Basic 认证Bearer Token 和 API Key 应通过自定义Authorization或其他请求头传递不要滥用auth。Bearer TokenJWT请求拦截器动态注入前后端分离项目中最常见的方式是把 JWT 放进Authorization请求头。官方推荐做法是在 axios 实例上挂请求拦截器让 token 在每次发请求时实时读取而非启动时缓存从而天然规避 token 过期后缓存值失效的问题import axios from axios; const api axios.create({ baseURL: https://api.example.com }); api.interceptors.request.use((config) { const token localStorage.getItem(access_token); if (token) { config.headers.set(Authorization, Bearer ${token}); } return config; });几个实现要点axios.create()创建独立实例后拦截器只作用于该实例便于把鉴权逻辑收敛到 API 客户端层config.headers是AxiosHeaders实例使用.set()方法而非直接赋值config.headers.Authorization是与 axios 1.x 兼容的推荐写法拦截器里读localStorage保证 token 是发请求瞬间的最新值这与后文token 续期方案配合使用。HTTP Basic 认证auth 选项与 URL 内嵌凭据对于使用 HTTP Basic 认证的 API直接传auth选项即可axios 会完成 Base64 编码并自动设置Authorization头const response await axios.get(https://api.example.com/data, { auth: { username: myUser, password: myPassword, }, });类型定义上index.d.ts中声明了专门的结构index.d.tsexport interface AxiosBasicCredentials { username: string; password: string; }AxiosRequestConfig与实例默认配置中都暴露了auth?: AxiosBasicCredentials见 index.d.ts。源码剖析resolveConfig 中的 Basic 编码逻辑auth选项的核心处理位于配置解析阶段 lib/helpers/resolveConfig.js// HTTP basic authentication if (auth) { const username utils.getSafeProp(auth, username) || ; const password utils.getSafeProp(auth, password) || ; try { headers.set( Authorization, Basic btoa(username : (password ? encodeUTF8(password) : )) ); } catch (e) { throw AxiosError.from(e, AxiosError.ERR_BAD_OPTION_VALUE, config); } }从源码可以看出三个关键实现细节密码支持非 Latin-1 字符密码会先经过 encodeUTF8encodeURIComponent转义 逐字节还原转成 Latin-1 字节串再交给btoa()因此open ßç£☃sesame这类非 ASCII 密码可以正确编码而用户名若含非 Latin-1 字符会导致btoa抛错并被包装成code: ERR_BAD_OPTION_VALUE的AxiosError。这两点都有测试佐证tests/browser/basicAuth.browser.test.js 分别验证了非 Latin-1 密码的成功编码与非法用户名的报错tests/unit/helpers/resolveConfig.test.js 验证了ERR_BAD_OPTION_VALUE包装。只读取自有属性utils.getSafeProp(auth, username)配合own()机制只读取实例自有属性专门防御原型链污染如Object.prototype.username被恶意注入。tests/unit/helpers/resolveConfig.test.js 中构造了Object.prototype.username继承场景断言结果只包含auth: {}自身字段编码出的Basic Og即: 的 Base64继承值被安全忽略。编码失败不静默Base64 编码异常会被包装为AxiosErrorERR_BAD_OPTION_VALUE抛出调用方可以按标准 axios 错误流程处理。URL 内嵌凭据的回退机制除显式auth选项外Node.js 的 http 适配器与 fetch 适配器还支持从请求 URL 中推断 Basic 凭据例如https://myUser:myPasswordapi.example.com/datafetch 适配器中该逻辑位于 lib/adapters/fetch.js与文档描述一致且有两个值得注意的实现行为// HTTP basic authentication let auth undefined; const configAuth own(auth); if (configAuth) { // 显式 auth 优先 auth { username, password }; } if (maybeWithAuthCredentials(url)) { const parsedURL new URL(url, platform.origin); // 仅当没有显式 auth 时才从 URL 解析凭据 if (!auth (parsedURL.username || parsedURL.password)) { auth { username: decodeURIComponentSafe(parsedURL.username), password: decodeURIComponentSafe(parsedURL.password), }; } // 无论凭据来自何处最终都会从 URL 中剥离 if (parsedURL.username || parsedURL.password) { parsedURL.username ; parsedURL.password ; url parsedURL.href; } } if (auth) { headers.delete(authorization); headers.set( Authorization, Basic btoa(encodeUTF8((auth.username || ) : (auth.password || ))) ); }显式auth选项优先if (!auth ...)保证 URL 内嵌凭据只是回退来源auth选项始终覆盖 URL 中的用户名密码。这也是官方文档对新代码的明确建议优先使用显式auth避免凭据散落在 URL 字符串里日志、document.referrer等途径更易泄漏。百分号编码会先解码decodeURIComponentSafe()lib/adapters/fetch.js会把 WHATWG URL 解析器返回的 percent-encoded 凭据解码例如my%40email.com:pass会按myemail.com:pass发送解码失败时回退原值而非抛错。URL 中的凭据会被剥离最终实际发出的 URL 不含用户名密码凭据只通过Authorization头传输同时会先headers.delete(authorization)防止手动设置的Authorization头与 Basic 凭据冲突。http 适配器lib/adapters/http.js实现等价逻辑将username:password组合后通过 Node 的auth请求选项下发同样先删authorization头再走 URL 回退。此外它还有一个细节——重定向时保留认证lib/adapters/http.js 通过beforeRedirects.auth钩子在 3xx 跳转后恢复auth避免跨路径重定向导致 Basic 凭据丢失。API Key请求头或查询参数二选一API Key 的传递方式由服务端约定决定axios 侧只需选择对应的传递通道// 方式一作为请求头推荐凭据不进入 URL const api axios.create({ baseURL: https://api.example.com, headers: { X-API-Key: your-api-key-here }, }); // 方式二作为查询参数 const response await axios.get(https://api.example.com/data, { params: { apiKey: your-api-key-here }, });两种方式的差异在于请求头方式在实例上配置一次即可全局生效且凭据不会出现在 URL 中——URL 更容易被代理、CDN、浏览器历史与日志记录因此除非 API 明确要求应优先选择请求头查询参数方式利用params自动做 URL 编码适合老式 API 的约定但注意 axios 不会对其做脱敏落日志时会完整暴露。Token 续期响应拦截器 失败请求队列当 access token 过期时需要静默刷新并重试失败的请求。官方文档给出的完整实现是响应拦截器 刷新锁 等待队列模式能避免并发请求同时触发多次刷新import axios from axios; const api axios.create({ baseURL: https://api.example.com }); // 跟踪是否已有刷新请求在途避免并发重复刷新 let isRefreshing false; let failedQueue []; const processQueue (error, token null) { failedQueue.forEach((prom) { if (error) { prom.reject(error); } else { prom.resolve(token); } }); failedQueue []; }; api.interceptors.response.use( (response) response, async (error) { const originalRequest error.config; if (error.response?.status 401 !originalRequest._retry) { if (isRefreshing) { // 已有刷新在途把当前请求挂起等刷新完成后再重试 return new Promise((resolve, reject) { failedQueue.push({ resolve, reject }); }) .then((token) { originalRequest.headers[Authorization] Bearer ${token}; return api(originalRequest); }) .catch((err) Promise.reject(err)); } originalRequest._retry true; isRefreshing true; try { const { data } await axios.post(/auth/refresh, { refreshToken: localStorage.getItem(refresh_token), }); const newToken data.access_token; localStorage.setItem(access_token, newToken); api.defaults.headers.common[Authorization] Bearer ${newToken}; processQueue(null, newToken); return api(originalRequest); } catch (refreshError) { processQueue(refreshError, null); // 刷新失败清理本地凭证跳转登录或派发全局事件 localStorage.removeItem(access_token); window.location.href /login; return Promise.reject(refreshError); } finally { isRefreshing false; } } return Promise.reject(error); } );该模式的三个关键点值得理解_retry标记防止死循环同一请求 401 后只允许自动重试一次如果刷新后的 token 仍然 401错误会原样上抛而不会无限循环。isRefreshing锁 failedQueue队列并发场景下只有第一个 401 请求真正发起刷新其余 401 请求挂起为 Promise 进入队列刷新成功时processQueue(null, newToken)统一放行并重放刷新失败时统一 reject。这是处理短时间大量请求同时过期的标准方案。刷新请求走裸axios而非api实例避免刷新请求本身又进入该拦截器虽然_retry也能兜底同时刷新成功后通过api.defaults.headers.common更新后续请求的默认头与请求拦截器配合形成完整闭环。Cookie 会话认证withCredentials 与 CORS 约束对于基于服务端会话、依赖 Cookie 的 API需要在实例上开启withCredentials: true让跨域请求携带 Cookieconst api axios.create({ baseURL: https://api.example.com, withCredentials: true, // 每次请求都携带 Cookie });需要注意服务端 CORS 的硬性约束withCredentials: true要求服务器响应Access-Control-Allow-Credentials: true且Access-Control-Allow-Origin必须是具体来源不能使用*通配符否则浏览器会直接拦截响应。从源码看该配置在不同适配器中有对应的落地实现XHR 适配器lib/adapters/xhr.js配置存在时直接透传给 XMLHttpRequest——request.withCredentials !!_config.withCredentialsfetch 适配器lib/adapters/fetch.js把布尔值映射为 fetch 的credentials模式——true映射为include、false映射为omit未设置时默认为same-originlib/adapters/fetch.js即默认只携带同源 Cookie行为与浏览器 fetch 规范一致http 适配器NodeNode 环境没有浏览器 Cookie 概念跨域请求的 Cookie 通常依赖http适配器内置的 Cookie 处理逻辑而非该选项withCredentials主要针对浏览器端跨域场景。另外axios 对同源请求默认会自动携带 XSRF TokenresolveConfig中lib/helpers/resolveConfig.js仅在标准浏览器环境且withXSRFToken true或 URL 同源时从xsrfCookieName指定的 Cookie 读取值并写入xsrfHeaderName请求头用于服务端防跨站请求伪造校验。做 Cookie 会话认证时可与服务端 CSRF 校验机制配合使用。选型小结OAuth2 / JWT 前后端分离请求拦截器注入 Bearer Token 响应拦截器做 401 自动续期是 axios 生态最完整的组合内网 / 服务间简单认证用auth选项并注意新代码优先显式auth而非 URL 内嵌凭据的官方建议——显式选项优先级更高且凭据不会残留在 URL 中第三方开放平台确认服务端约定后用实例默认头或params传递 API Key优先请求头同域会话 / SSOwithCredentials: true并确认服务端 CORS 头满足Access-Control-Allow-Credentials: true 具体 Origin 的要求。以上所有配置项与行为均可在当前仓库源码中查证核心编码逻辑见 lib/helpers/resolveConfig.js各适配器的凭据处理见 lib/adapters/fetch.js、lib/adapters/http.js、lib/adapters/xhr.js行为验证可参考 tests/browser/basicAuth.browser.test.js 与 tests/unit/helpers/resolveConfig.test.js。【免费下载链接】axiosPromise based HTTP client for the browser and node.js项目地址: https://gitcode.com/GitHub_Trending/ax/axios创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

2026/9/5 21:11:19

Svelte style: 指令完全指南:从模板语法到编译与运行时实现

Svelte style: 指令完全指南:从模板语法到编译与运行时实现 【免费下载链接】svelte web development for the rest of us 项目地址: https://gitcode.com/GitHub_Trending/sv/svelte 本篇基于 Svelte 官方文档中的 style: 指令说明,系统讲解这一…

2026/9/5 21:11:19

蓝牙音箱系统设计实战:从模块划分到整机验证

蓝牙音箱是消费电子里少有的“四合一”项目:射频、音频、电源、声学,任何一个方向单独拿出来都能养一个工程师岗位,但在这类产品里,所有人必须围绕同一个腔体和同一块 PCB 协作。这也是为什么很多蓝牙音箱项目开案时各模块都正常&…

2026/9/5 21:11:19

AGENTS.md 使用教程:三步让 AI 编程代理读懂你的项目

AGENTS.md 使用教程:三步让 AI 编程代理读懂你的项目 【免费下载链接】agents.md AGENTS.md — a simple, open format for guiding coding agents 项目地址: https://gitcode.com/GitHub_Trending/ag/agents.md AGENTS.md 是一个开放、无门槛的标准文件格式…

2026/9/5 2:46:54

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/9/5 2:46:52

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/9/5 2:44:34

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/9/5 0:04:47

流式背压机制:避免前端渲染卡死与内存暴涨的滑动窗口限流

流式背压机制:避免前端渲染卡死与内存暴涨的滑动窗口限流在大模型流式输出(Streaming)与智能体实时推流的架构中,生产环境中经常出现一种“上下游生产消费速率严重失衡”的极端情况: 生产端极速产出:大模型…

2026/9/5 2:45:13

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/5 2:30:42

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/5 2:46:50

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…