浏览器没有为跨源请求设置源头?

Posted

技术标签:

【中文标题】浏览器没有为跨源请求设置源头?【英文标题】:Browser not setting the origin header for cross origin requests? 【发布时间】:2018-07-23 01:29:45 【问题描述】:

我有一个简单的index.html 文件。此 html 正在从 localhost:3000 加载

<body>
    <h1>Some app</h1>
    <script src="http://localhost:3005/script.js"></script>
</body>

script.js 设置为从另一个来源加载:localhost:3005

据我了解,浏览器应该拦截请求并将 origin 标头 添加到其中 - 并向localhost:3005 服务器发出 preflight request 以检查 @987654331 @ 是允许的。

但我没有得到origin。浏览器似乎没有添加源头。 这是负责提供 script.js 文件 (localhost:3005) 的服务器。我正在使用cors module。

const app = express()

const whitelist = ["http://localhost:3001"]
const corsOptions = 
    origin: function(origin, callback) 
        console.log("origin is: ", origin);      //undefined -- why is undefined??

        if (whitelist.indexOf(origin) !== -1) 
            callback(null, true)
        
        else 
            callback(new Error('Not allowed by CORS'))
        
    


app.use(cors(corsOptions), express.static(__dirname))
app.listen(3005, () => 
    console.log("server listening on port 3005")
)

我的实际目标是localhost:3000 列入白名单,以请求我的script.js

我输入 localhost:3001 只是为了测试我是否真的遇到了 cors 错误 - 应该是这样。

但我什至不知道起源 - 是什么原因造成的? 我在 Firefox 和 Chrome 中都得到了相同的行为。我误解了这个孔的过程吗?谢谢:)

编辑:也许看到请求会有所帮助

【问题讨论】:

浏览器不会为获取 src URL 的请求发送 Origin 请求标头。这些请求是在获取模式设置为“no-cors”的情况下发出的,并且不会为“no-cors”请求发送 Origin 请求标头。基本上,浏览器仅针对使用 XHR 或 Fetch API(或基于 XHR 或 Fetch API 构建的 javascript 库 Ajax 方法)发出的请求或请求 HTTP 方法不是 GET 或请求已启动时发送 Origin 标头来自具有“crossorigin”属性的 HTML 元素。 fetch.spec.whatwg.org有详情 【参考方案1】:

我认为您可能误解了 CORS 的目的。它使服务器能够选择加入某些类型的请求,否则这些请求将在浏览器的同源策略下被禁止。它没有提供一种机制来禁止以前允许的请求。

&lt;script&gt; 标记的src 中执行来自外部来源的脚本始终在同源策略下被允许,因此CORS 根本不适用。这就是请求中没有标头的原因。

我的实际目标是仅将localhost:3000 列入白名单,以请求我的script.js

您不能为此使用 CORS。事实上,你可能根本无法做到这一点。我会退后一步,问你为什么要这样做。如果您尝试保护私有数据,那么可能需要某种身份验证机制(令牌、cookie 等)。

【讨论】:

感谢您的回答,这对我有帮助。我正在为服务器图像构建一个 API,因此这些图像通常是通过另一个网站的 &lt;img&gt; 标签请求的。有什么方法可以让我知道这些请求来自哪个主机? @Jauny:查看Referer 标头,这可能是您最好的选择。 是的,你是对的!我得到了一个空的referer,因为我所有的请求都来自同一个域,但是现在我得到了外部请求,它正在工作!【参考方案2】:

对于可能遇到此问题的其他人,这里是 Kevin Christopher Henry 在上面接受的答案的实际演示。

下面的第一个代码 sn-p 从域 www.w3schools.com 请求一个 脚本(带有 src URL 的 .js 文件)(并且在请求成功时也会自动执行它,但那是这里不重要)。这里需要注意两点:

    此脚本请求是针对不同于其来源的域 (www.w3schools.com) 发出的运行成功。

$.ajax(
  url: 'https://www.w3schools.com/lib/w3codecolor.js',
  dataType: "script",
  success: function(data, status) 
    console.log('Result:', status)
  ,
  error: function(err, status) 
    console.log('Error:', error);
  ,
);
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

下面的第二个代码 sn-p 使用 XHR 从域 www.w3schools.com 请求一个指向特定路由/页面的 URL (https://www.w3schools.com/bootstrap)。这是您在向 API 端点发出请求时将使用的内容。 这是 CORS 的管辖范围。这里需要注意两点:

    此请求是针对不同于其来源的域 (www.w3schools.com) 发出的这会失败,因为现代浏览器默认限制跨域 HTTP 请求 (see more)。现在解决这个问题的唯一方法是在 www.w3schools.com 域上配置 CORS 以接受来自其自身域之外的 XHR 请求。

$.ajax(
  url: 'https://www.w3schools.com/bootstrap',
  success: function(data, status) 
    console.log('Result:', status)
  ,
  error: function(err, status) 
    console.log('Error:', err);
  ,
);
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

这里的错误是模棱两可的。要查看实际的 CORS 错误,请打开 Web Developers Console,您应该会看到类似

的内容
"Access to XMLHttpRequest at 'https://www.w3schools.com/bootstrap' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."

现在错误显示“from origin 'null'”的原因是因为这些代码 sn-ps 可能是在沙盒环境中运行的,它甚至没有将请求标头 Origin 设置为“https://***.com”。

但是,如果 Origin 实际上设置为“https://***.com”,结果将是相同的。随意将上述脚本复制粘贴到 Web Developer Console 中并尝试一下。

【讨论】:

这个例子中的区别不是很清楚。第一个请求成功,因为 jquery 添加了“sec-fetch-mode: no-cors”标头,第二个请求由于没有该标头而失败。如果你尝试 fetch("w3schools.com/bootstrap", mode: 'no-cors') 你可以看到它工作。

以上是关于浏览器没有为跨源请求设置源头?的主要内容,如果未能解决你的问题,请参考以下文章

为跨源请求设置 cookie

Cookie不会在跨源请求中发送

Internet Explorer 11 不在 CORS 请求中添加 Origin 标头?

为跨浏览器功能设置选择菜单样式的正确方法[重复]

浏览器中的“跨源请求被阻止:同源策略”错误

Ajax中的跨域请求(跨源请求)