乐闻世界logo
搜索文章和话题

JS 代码为什么 会显示一个无访问控制的allow origin的 header ?

7 个月前提问
3 个月前修改
浏览次数45

6个答案

1
2
3
4
5
6

在Web开发中,JavaScript代码尝试执行跨源HTTP请求时,可能会遇到与访问控制(CORS)相关的问题。CORS是一种由许多浏览器实现的安全功能,用来防止恶意网站读取另一个网站的数据。当JavaScript尝试从另一个源(域名、协议或端口不同)加载资源时,浏览器会执行CORS检查,看看请求的资源是否通过了相应的访问控制检查。

问题中提到的“无访问控制的allow origin的 header”通常是指后端服务器在响应中包含了一个Access-Control-Allow-Origin: *的HTTP头。这个HTTP头的存在告诉浏览器允许来自任何源的访问请求,这样做可以增加资源的可访问性,但同时也降低了安全性,因为任何网站都可以读取这些数据。

例子

假设您有一个API部署在https://api.example.com上,该API提供了用户信息。如果后端配置为发送Access-Control-Allow-Origin: *头,那么任何网站都可以向这个API发起请求并读取数据。

JavaScript代码示例:

javascript
fetch("https://api.example.com/user/data") .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error));

在这个例子中,如果api.example.com的响应包括Access-Control-Allow-Origin: *头,那么即使是从任何其他源(例如从不同的域名https://anotherdomain.com)发出的请求,浏览器也会允许这个跨源请求成功,并且JavaScript能够处理返回的数据。

安全考虑

虽然使用Access-Control-Allow-Origin: *可以简化开发,使得任何人都可以从任何地方访问您的资源,但这通常不适用于包含敏感数据或需要身份验证的API。在这些情况下,最好限制访问源,只允许特定的域名或使用更加严格的CORS策略。

通常,为了增强安全性,推荐的做法是在服务器端配置一个明确的白名单,列出允许访问该资源的域名,而不是使用*,这样可以有效控制哪些网站可以请求您的资源。

总之,Access-Control-Allow-Origin: *头的使用可以使资源跨域访问变得更加容易,但应谨慎使用,特别是在处理需要保护的数据时。在实际应用中,应根据具体需求和安全策略来设置适当的CORS策略。

2024年6月29日 12:07 回复

如果我理解正确的话,您正在对与您的页面所在的域不同的域执行XMLHttpRequest 。因此,浏览器会阻止它,因为出于安全原因,它通常允许同一来源的请求。当你想要进行跨域请求时,你需要做一些不同的事情。

当您使用 Postman 时,它们不受此政策的限制。引用自_跨源 XMLHttpRequest_:

常规网页可以使用 XMLHttpRequest 对象从远程服务器发送和接收数据,但它们受到同源策略的限制。扩展并没有如此限制。只要扩展程序首先请求跨源权限,就可以与其源之外的远程服务器进行通信。

2024年6月29日 12:07 回复

**警告:**使用Access-Control-Allow-Origin: *可能会使您的 API/网站容易受到跨站点请求伪造(CSRF) 攻击。在使用此代码之前,请确保您了解风险

如果您使用PHP ,解决起来非常简单。只需在处理请求的 PHP 页面的开头添加以下脚本:

shell
<?php header('Access-Control-Allow-Origin: *'); ?>

如果您使用Node-red,则必须通过取消注释以下行来允许文件中的CORS :node-red/settings.js

shell
// The following property can be used to configure cross-origin resource sharing // in the HTTP nodes. // See https://github.com/troygoode/node-cors#configuration-options for // details on its contents. The following is a basic permissive set of options: httpNodeCors: { origin: "*", methods: "GET,PUT,POST,DELETE" },

如果您使用与问题相同的Flask ;你必须先安装flask-cors

shell
pip install -U flask-cors

然后将 Flask _cors_包包含在您的应用程序中。

shell
from flask_cors import CORS

一个简单的应用程序将如下所示:

shell
from flask import Flask from flask_cors import CORS app = Flask(__name__) CORS(app) @app.route("/") def helloWorld(): return "Hello, cross-origin-world!"

更多细节可以查看Flask 文档

2024年6月29日 12:07 回复

因为
$.ajax({type: "POST" - 调用OPTIONS
$.post( - 调用POST

两者是不同的。邮递员正确地调用“POST”,但当我们调用它时,它将是“OPTIONS”。

对于 C# Web 服务 - Web API

请将以下代码添加到_web.config_文件中的 <system.webServer> 标记下。这将起作用:

shell
<httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> </customHeaders> </httpProtocol>

请确保您在 Ajax 调用中没有犯任何错误。

jQuery

shell
$.ajax({ url: 'http://mysite.microsoft.sample.xyz.com/api/mycall', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, type: "POST", /* or type:"GET" or type:"PUT" */ dataType: "json", data: { }, success: function (result) { console.log(result); }, error: function () { console.log("error"); } });

注意:如果您正在寻找从第三方网站下载内容,那么这对您没有帮助。您可以尝试以下代码,但不能尝试 JavaScript。

shell
System.Net.WebClient wc = new System.Net.WebClient(); string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
2024年6月29日 12:07 回复

深的

在下面的 API 调查中,我使用http://example.com而不是您问题中的 http://myApiUrl/login ,因为第一个有效。我假设您的页面位于http://my-site.local:8088

注意:API 和您的页面具有不同的域!

您看到不同结果的原因是 Postman:

  • 设置标头Host=example.com(您的 API)
  • 未设置标题Origin
  • Postman 实际上根本不使用你的网站 url(你只需在 Postman 中输入你的 API 地址) - 他只向 API 发送请求,所以他假设该网站与 API 具有相同的地址(浏览器不会假设这一点)

这类似于当站点和 API 具有相同域时浏览器发送请求的方式(浏览器也设置 header item Referer=http://my-site.local:8088,但我在 Postman 中没有看到它)。当_未_Origin设置header时,通常服务器默认允许此类请求。

在此输入图像描述

这是 Postman 发送请求的标准方式。但是,当您的站点和 API 具有不同的域时,浏览器会以不同的方式发送请求,然后CORS就会发生,浏览器会自动:

  • 设置标头Host=example.com(您的 API)
  • 设置标题Origin=http://my-site.local:8088(您的网站)

(标头Referer的值与 相同Origin)。现在,在 Chrome 的_控制台和网络_选项卡中,您将看到:

在此输入图像描述

在此输入图像描述

当你有**Host != Origin这个就是CORS,当服务器检测到这样的请求时,它通常会默认阻止它**。

Origin=null当您从本地目录打开 HTML 内容时设置,并且它发送请求。同样的情况是当您在 中发送请求时<iframe>,如下面的代码片段所示(但这里Host根本没有设置标头) - 一般来说,在 HTML 规范提到不透明来源的任何地方,您都可以将其转换为Origin=null.您可以在此处找到有关此内容的更多信息。

shell
fetch('http://example.com/api', {method: 'POST'}); Look on chrome-console > network tab

运行代码片段Hide results

展开片段

如果您不使用简单的 CORS 请求,通常浏览器还会在发送主请求之前自动发送 OPTIONS 请求 - 更多信息请参见此处。下面的代码片段展示了这一点:

shell
fetch('http://example.com/api', { method: 'POST', headers: { 'Content-Type': 'application/json'} }); Look in chrome-console -> network tab to 'api' request. This is the OPTIONS request (the server does not allow sending a POST request)

运行代码片段Hide results

展开片段

您可以更改服务器的配置以允许 CORS 请求。

下面是一个在 nginx(nginx.conf 文件)上打开 CORS 的示例配置-always/"$http_origin"对 nginx 和Apache的设置要非常小心"*"- 这将从任何域中解除对 CORS 的阻止(在生产中,而不是使用您的具体页面地址,而不是使用您的具体页面地址)应用程序编程接口)

显示代码片段

shell
location ~ ^/index\.php(/|$) { ... add_header 'Access-Control-Allow-Origin' "$http_origin" always; add_header 'Access-Control-Allow-Credentials' 'true' always; if ($request_method = OPTIONS) { add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above) add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin'; add_header 'Content-Length' 0; add_header 'Content-Type' 'text/plain charset=UTF-8'; return 204; } }

Run code snippetHide results

Expand snippet

以下是在 Apache 上打开 CORS 的示例配置(.htaccess 文件)

显示代码片段

shell
# ------------------------------------------------------------------------------ # | Cross-domain Ajax requests | # ------------------------------------------------------------------------------ # Enable cross-origin Ajax requests. # http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity # http://enable-cors.org/ # <IfModule mod_headers.c> # Header set Access-Control-Allow-Origin "*" # </IfModule> # Header set Header set Access-Control-Allow-Origin "*" # Header always set Access-Control-Allow-Credentials "true" Access-Control-Allow-Origin "http://your-page.com:80" Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT" Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"

Run code snippetHide results

Expand snippet

2024年6月29日 12:07 回复

应用 CORS 限制是一项由服务器定义并由浏览器实现的安全功能。

浏览器查看服务器的 CORS 策略并遵守它。

然而,Postman工具并不关心服务器的CORS策略。

这就是为什么 CORS 错误出现在浏览器中,但没有出现在 Postman 中。

2024年6月29日 12:07 回复

你的答案