Vite内置http-proxy移除前端Authorization头后,无法自动添加目标服务配置的Basic Auth认证头问题
我太懂你这个痛点了!你已经把前端传来的Bearer JWT校验逻辑写好了,也成功移除了前端的Authorization头,但目标服务需要的Basic Auth却没自动加上——这其实是因为当我们手动介入proxyReq事件修改请求头时,Vite/http-proxy默认的Basic Auth注入逻辑已经提前执行过,或者被我们的自定义逻辑覆盖了。
问题根源
Vite的代理基于http-proxy库,默认情况下如果你在target里配置了auth参数,它会自动生成Basic Auth头并添加到请求中。但这个默认操作是在proxyReq事件触发前完成的,当我们在proxyReq里移除了Authorization头之后,原来自动生成的Basic Auth头也被一起删掉了,而且不会再自动重新添加。
解决方案:手动生成并添加Basic Auth头
我们可以在自定义的proxyReq逻辑里,完成JWT校验和移除前端头之后,手动读取当前代理配置的auth信息,生成对应的Basic Auth头并设置到请求里。这样就能完美衔接两种认证方式。
第一步:写个生成Basic Auth头的工具函数
这个函数把user:password格式的字符串转换成标准的Basic Auth头格式:
function generateBasicAuthHeader(authString: string): string { // 将用户名密码转为base64编码 const encodedCredentials = Buffer.from(authString).toString('base64'); return `Basic ${encodedCredentials}`; }
第二步:修改你的configure函数
在移除前端的Authorization头之后,添加手动注入Basic Auth的逻辑:
import { defineConfig, ProxyOptions } from 'vite'; import react from '@vitejs/plugin-react'; function generateBasicAuthHeader(authString: string): string { const encodedCredentials = Buffer.from(authString).toString('base64'); return `Basic ${encodedCredentials}`; } const configure: ProxyOptions["configure"] = (proxy, options) => { proxy.on("proxyReq", function (proxyReq, req, res) { // 校验前端传来的JWT Token const authHeader = proxyReq.getHeader("authorization")?.toString(); const [tokenType, token] = authHeader ? authHeader.split(" ") : []; if (tokenType !== "Bearer" || !token) { res.writeHead(401, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "unauthorized", error_description: "Invalid or missing access token", })); return; } // 移除前端的Bearer授权头 proxyReq.removeHeader("authorization"); // 手动添加目标服务的Basic Auth头 if (options.target?.auth) { const basicAuth = generateBasicAuthHeader(options.target.auth); proxyReq.setHeader("authorization", basicAuth); } }); }; export default defineConfig({ plugins: [react()], server: { open: true, proxy: { "/api/service1": { target: { protocol: "http", auth: `user1:pass1`, host: "localhost", port: 3700, }, changeOrigin: true, configure, }, "/api/service2": { target: { protocol: "http", auth: `user2:pass2`, host: "localhost", port: 3600, }, changeOrigin: true, configure, }, "/api/service3": { target: { protocol: "http", auth: `user3:pass3`, host: "localhost", port: 3800, }, changeOrigin: true, configure, }, }, }, });
为什么这样可行?
我们在proxyReq事件里,先完成JWT的校验逻辑,确认无误后移除前端的Bearer头,接着从当前代理的配置中取出auth字段,生成标准的Basic Auth头并设置到请求里。这样就确保了目标服务能收到它需要的认证信息,同时也完成了前端JWT的校验。
小提示
- 可以在
proxyReq里加个console.log(proxyReq.getHeader("authorization")),确认Basic Auth头已经正确添加。 - 如果用TypeScript,可能需要给
options.target加个类型断言,比如(options.target as { auth?: string })?.auth,避免类型报错。
这样修改后,你的代理就能完美实现“前端JWT校验 → 替换为目标服务Basic Auth”的流程啦!
内容来源于stack exchange

