vite代理,get请求正常,post请求403问题

Daotin 于 2024-12-16 发布 编辑

背景

今天在开发vite+vue项目的时候,遇到一个非常棘手的问题。

在项目登录的界面,通过get获取验证码是ok的,但是通过post调用登录接口报403。

此时,已经使用vite做了代理,但是后端并未收到请求,所以403只能是前端报的,而不是后端返回的。

分析

1、根据AI的提示,检查Content-Type是否有问题。

没有问题,设置的是'Content-Type': 'application/json;charset=utf-8',,即便请求的内容加密成字符串了,当设置这个请求头后,后端在解密字符串后,就会成为json格式的请求。

2、跨域问题

虽然提示Invalid CORS request,但是没有很明显的项目中遇到的跨域提示,而且设置了vite代理,应该不存在跨域问题。

是不是代理方式写的不对?经过AI检查,没有问题。

3、服务器端限制

不可能,服务未到达服务器。

4、网络问题?

比如断网?那也不会,验证码都可以请求到。

5、如果前端data错误或者header错误,会有403错误吗?

AI:在请求到达后端的情况下,前端 data 或 headers 的错误确实可能引发 403 Forbidden 错误,但具体取决于后端的逻辑。如果请求根本没有到达后端,问题一般不会是 data 或 headers,而是跨域配置、网络问题、或者请求本身的阻止。

6、通过curl -X POST -H 'Content-Type: application/json' -d 'xxx...' http://10.8.3.48:8082/login 的方式却可以到达后端,但是vite代理不能到达,难道vite拦截了?

通过加入vite的打印信息,可以看到确实没有成功:

server: {
    proxy: {
        [env.VITE_BASE_API]: {
            target: env.VITE_PROXY_URL,
            changeOrigin: true,
            rewrite: path => path.replace(new RegExp(`^${env.VITE_BASE_API}`), ''),
            configure: (proxy, options) => {
                // 添加代理事件监听器,用于调试
                proxy.on('proxyReq', (proxyReq, req, res) => {
                    console.log('Proxy Request:', {
                        url: req.url,
                        headers: proxyReq.getHeaders()
                    });
                });
                proxy.on('proxyRes', (proxyRes, req, res) => {
                    console.log('Proxy Response:', {
                        statusCode: proxyRes.statusCode,
                        headers: proxyRes.headers
                    });
                });
            }
        }
    }
}

那就很奇怪了。

AI说,可能是因为baseURL 带了具体的域名,那么就不会走vite代理了吗?必须是一个相对地址吗?

是的,如果 baseURL 带了具体的域名(例如 'http://localhost:5173/dev-api'),请求不会走 Vite 的代理。这是因为 Vite 的代理配置 (server.proxy) 只对相对路径(例如 /api/dev-api)生效。如果请求中带有完整的 URL(即包含协议和域名),浏览器会直接发起请求到该域名,而不会通过本地开发服务器的代理。

所以,需要修改domain.js代码:

const nodeEnv = import.meta.env.VITE_APP_NODE_ENV || 'development'
const target = import.meta.env.VITE_PROXY_URL

const getBaseURL = () => {
    // 本地开发环境
    if (nodeEnv === 'development') {
        // return `${location.origin}${import.meta.env.VITE_BASE_API}`
        // 修改为
        // 只返回 base api 路径,让代理服务器处理
        return import.meta.env.VITE_BASE_API
    }
    // 线上生产环境
    return target
}

export const baseURL = getBaseURL()

修改后,依然报403错误。

没办法了,最后在google搜索得到答案。

解决

解决方案:在vite代理的请求中,移除请求头referer和origin。

server: {
    open: false,
    host: '0.0.0.0',
    proxy: {
        [env.VITE_BASE_API]: {
            target: env.VITE_PROXY_URL,
            changeOrigin: true,
            rewrite: path => path.replace(new RegExp(`^${env.VITE_BASE_API}`), ''),
            configure: (proxy, options) => {
                // 添加代理事件监听器,用于调试
                proxy.on('proxyReq', (proxyReq, req, res) => {
                    proxyReq.removeHeader('referer') // 移除请求头
                    proxyReq.removeHeader('origin') // 移除请求头
                })
            },
        },
    },
},

原因:在使用 Vite 的代理时,POST 请求返回 403 通常是由于代理或目标服务器对 Referer 和 Origin 字段的校验引发的。代理服务器可能会因为这两个字段不符合预期而拦截请求,而非直接转发给目标服务器。移除这两个字段可以绕过代理或目标服务器的来源校验,从而使请求成功。

然而,有些项目未移除这些字段也能成功,可能是因为代理配置(如 changeOrigin: true)自动伪装了请求来源,或目标服务器对来源字段校验宽松。

参考地址:https://blog.csdn.net/m0_73334325/article/details/131254774