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

Chrome访问127.0.0.1时Origin Header发送错误问题咨询

问题描述

摘要

当前端部署在http://localhost:5173时,向http://127.0.0.1:8000发送CORS请求会出现Origin Header错误:

  • 预期Origin Header:Origin: http://localhost:5173
  • 实际Origin Header:Origin: http://127.0.0.1(主机错误且缺失端口)

该问题仅在后端目标为127.0.0.1:8000时出现,若目标为localhost:8000,Origin Header则正常。

详细说明

测试自研Web应用时,前端(localhost:5173)点击按钮向后端发送HTTP请求:

  • 当请求目标为http://localhost:8000时,预检请求携带Origin: http://localhost:5173,符合预期。
  • 当请求目标为http://127.0.0.1:8000时,预检请求的Origin Header变为Origin: http://127.0.0.1,并非正确的源(应为http://localhost:5173)。

即使启用CORS插件,错误的Origin Header会导致后端返回错误的Access-Control-Allow-Origin响应头,进而触发CORS报错。

提供了示例Python代码,可启动两个服务器(端口5173和8000),前端页面包含两个按钮,点击后可观察预检请求的Origin Header问题。

核心问题

该行为是Google Chrome的Bug,还是存在合理的设计依据?

环境配置

  • MacBook Pro (Apple M3 Max)
  • MacOS Sequoia 15.4.1
  • Chrome Version 136.0.7103.114 (Official) (arm64)

演示代码

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
import uvicorn

app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "*",
    ],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
@app.get("/test")
async def test():
    return JSONResponse(content={"message": "Success from backend"})


frontend_app = FastAPI()
@frontend_app.get("/", response_class=HTMLResponse)
async def index(request: Request):
    html_content = """
    <!DOCTYPE html>
    <html>
    <head>
        <title>CORS Test</title>
    </head>
    <body>
        <h1>CORS Origin Test (127.0.0.1 vs localhost)</h1>
        <button onclick="request127()">Request 127.0.0.1:8000</button>
        <button onclick="requestLocalhost()">Request localhost:8000</button>
        <pre id="result"></pre>

        <script>
            async function request127() {
                try {
                    const res = await fetch('http://127.0.0.1:8000/test', {
                        method: 'GET',
                        headers: { authorization: 'Bearer token' }
                    });
                    const data = await res.json();
                    document.getElementById('result').innerText = '127.0.0.1 Result: ' + JSON.stringify(data);
                } catch (err) {
                    console.error(err);
                    document.getElementById('result').innerText = '127.0.0.1 Failed';
                }
            }

            async function requestLocalhost() {
                try {
                    const res = await fetch('http://localhost:8000/test', {
                        method: 'GET',
                        headers: { authorization: 'Bearer token' }
                    });
                    const data = await res.json();
                    document.getElementById('result').innerText = 'localhost Result: ' + JSON.stringify(data);
                } catch (err) {
                    console.error(err);
                    document.getElementById('result').innerText = 'localhost Failed';
                }
            }
        </script>
    </body>
    </html>
    """
    return HTMLResponse(content=html_content)


def run_backend():
    uvicorn.run(app, host="127.0.0.1", port=8000)


def run_frontend():
    uvicorn.run(frontend_app, host="127.0.0.1", port=5173)

if __name__ == "__main__":
    import multiprocessing

    p1 = multiprocessing.Process(target=run_backend)
    p2 = multiprocessing.Process(target=run_frontend)

    p1.start()
    p2.start()

    p1.join()
    p2.join()

运行步骤

pip install fastapi uvicorn
python test_server.py

解答

这不是Chrome的Bug,而是浏览器针对本地回环地址同源策略的特殊设计,背后有明确的安全与开发优化考量:

  1. 回环地址的同源豁免逻辑
    Chrome等浏览器会将localhost和127.0.0.1视为同一“本地信任域”,在处理跨域请求时会触发特殊的Origin替换规则:当页面来自localhost端口,请求目标为127.0.0.1时,浏览器会将Origin头替换为http://127.0.0.1(省略端口)。这是为了简化本地开发中的跨域验证——本地回环地址通常被认为是安全的,浏览器默认假设同一回环地址下的不同端口属于同一信任上下文。

  2. 端口省略的原因
    对于回环地址,浏览器认为端口不影响同源信任关系,因此生成Origin头时会自动省略端口。这是浏览器对本地开发场景的优化,但会导致CORS验证问题:后端CORS中间件会严格匹配Origin值,错误的Origin会导致响应头不匹配,触发报错。

  3. 解决方案

  • 统一使用localhost或127.0.0.1作为前后端的访问地址,避免混合使用;
  • 若必须混合使用,后端CORS配置需同时允许http://localhost:5173和http://127.0.0.1两个Origin;
  • 本地开发测试时,可通过Chrome启动参数--disable-web-security临时关闭同源策略(禁止生产环境使用)。

内容的提问来源于stack exchange,提问作者Jensen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 02:22:05