You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vite内置http-proxy移除前端Authorization头后,无法自动添加目标服务配置的Basic Auth认证头问题

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.09 03:03:07