浏览器没有为跨源请求设置源头?
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 的目的。它使服务器能够选择加入某些类型的请求,否则这些请求将在浏览器的同源策略下被禁止。它没有提供一种机制来禁止以前允许的请求。
在<script>
标记的src
中执行来自外部来源的脚本始终在同源策略下被允许,因此CORS 根本不适用。这就是请求中没有标头的原因。
我的实际目标是仅将
localhost:3000
列入白名单,以请求我的script.js
。
您不能为此使用 CORS。事实上,你可能根本无法做到这一点。我会退后一步,问你为什么要这样做。如果您尝试保护私有数据,那么可能需要某种身份验证机制(令牌、cookie 等)。
【讨论】:
感谢您的回答,这对我有帮助。我正在为服务器图像构建一个 API,因此这些图像通常是通过另一个网站的<img>
标签请求的。有什么方法可以让我知道这些请求来自哪个主机?
@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);
,
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
下面的第二个代码 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);
,
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
这里的错误是模棱两可的。要查看实际的 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') 你可以看到它工作。以上是关于浏览器没有为跨源请求设置源头?的主要内容,如果未能解决你的问题,请参考以下文章