Appearance
目标
- 保留按前缀(如
/api/pub)自动放行的白名单机制; - 支持逐请求显式关闭鉴权(即便该接口不在白名单里);
- 避免与 Axios 自带的
config.auth(Basic Auth)混淆; - 兼容历史
(req as any).auth写法,渐进迁移到useAuth。
方案总览
- 类型扩展:给
AxiosRequestConfig增加useAuth?: boolean。 - 对象式入口透传:
http.call({... useAuth })直达拦截器。 - 拦截器优先级:优先读
useAuth→ 回退老的auth→ 再按前缀与实例默认值判定。 - 显式移除头:当不需要鉴权时,从请求头里删除
Authorization,避免误带默认 token。 - 调用方式:
http.get/post(..., { useAuth:false })或http.call({ useAuth:false })。
关键改动(最小补丁)
1) 扩展 Axios 配置
避免与 Basic Auth 的
config.auth冲突,用单独的useAuth。
ts
// src/types/http/axios.d.ts
declare module "axios" {
export interface AxiosRequestConfig {
/** 覆盖实例默认鉴权:true=强制带token;false=强制不带token */
useAuth?: boolean;
}
}2) 对象式入口支持 useAuth
ts
// src/lib/http/types.ts(RequestOptions 中新增)
useAuth?: booleants
// src/lib/http/call.ts(buildAxiosConfigFromOptions 末尾透传)
if (typeof (options as any).useAuth === "boolean") {
(cfg as any).useAuth = (options as any).useAuth;
}3) 请求拦截器:判定与显式移除头
ts
// src/lib/http/client.ts(拦截器内替换判定片段)
// 1) 优先 useAuth,回退旧的 auth
const explicitAuth =
typeof (req as any).useAuth === "boolean"
? (req as any).useAuth
: typeof (req as any).auth === "boolean"
? (req as any).auth
: undefined;
const needAuth = explicitAuth ?? (authDefault && !isPublicByPrefix);
const accToken = storage.get(ACCESS_TOKEN);
const tokenType = storage.get(TOKEN_TYPE) || "Bearer";
// 2) 不需要鉴权:显式移除 Authorization,避免误带默认头
if (!needAuth) {
const h = (req.headers || {}) as Record<string, any>;
delete h.Authorization;
delete h.authorization;
req.headers = h;
} else {
// 需要鉴权但无 token:中断
if (!accToken) {
abortController.abort();
return Promise.reject(new Error("UNAUTHENTICATED"));
}
// 需要鉴权且有 token:注入
req.headers = { ...req.headers, Authorization: `${tokenType} ${accToken}` };
}调用方式示例
A) 传统 axios 三参(推荐)
ts
// 公开接口(不走 /api/pub,但也不需要 token)
await http.get("/api/third/get_login_credential_code", { useAuth: false });
// POST 且不带 token
await http.post("/api/third/login_by_credential", payload, { useAuth: false });B) 对象式入口
ts
await http.call({
url: "/api/third/get_login_credential_code",
method: "GET",
useAuth: false,
});
await http.call({
url: "/api/third/login_by_credential",
method: "POST",
data: payload,
useAuth: false,
});兼容与迁移
- 旧代码里的
(req as any).auth = false仍可用(拦截器已回退支持),但建议逐步统一到useAuth。 - 仍保留
publicPrefixes(如/api/pub)自动放行;useAuth:false仅在个别不走白名单的公开接口上使用。
常见坑
- 不要再用
config.auth = false:那是 Basic Auth,类型不对、语义也不对。 - 如果调用过
http.setAuthToken写了默认头,不显式移除就会误带 token;本方案在拦截器中已处理。 - 确保
tsconfig.json的include覆盖到src/types,让编辑器识别useAuth类型。
验收清单
- [ ]
src/types/http/axios.d.ts已生效(编辑器能识别useAuth)。 - [ ]
http.call能接收useAuth并透传到拦截器。 - [ ] 拦截器在
useAuth:false时不发送 Authorization;在需要鉴权但无 token 时立即中断。 - [ ] 现网公开接口(不在
/api/pub)能通过{ useAuth:false }正常调用。
结论:这套改动小而稳,语义清晰、类型安全,满足“前缀白名单 + 逐请求显式关闭鉴权”的企业级最佳实践。
::contentReference[oaicite:0]{index=0}