修改说明:这个问题是关于为什么XMLHttpRequest/fetch等。在浏览器上,Postman不受相同访问策略限制(您会收到提到CORB或CORS的错误)。这个问题不是关于如何修复“No‘Access Control Allow Origin’…”错误。这是关于它们发生的原因。
请停止发布:阳光下每种语言/框架的CORS配置。而是找到相关语言/框架的问题。允许请求绕过CORS的第三方服务用于关闭各种浏览器的CORS的命令行选项
我试图通过连接RESTful API内置Flask来使用JavaScript进行授权。但是,当我发出请求时,我会收到以下错误:
XMLHttpRequest cannot load http://myApiUrl/login.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'null' is therefore not allowed access.
我知道API或远程资源必须设置标头,但当我通过Chrome扩展Postman发出请求时,为什么它会起作用?
这是请求代码:
$.ajax({
type: 'POST',
dataType: 'text',
url: api,
username: 'user',
password: 'pass',
crossDomain: true,
xhrFields: {
withCredentials: true,
},
})
.done(function (data) {
console.log('done');
})
.fail(function (xhr, textStatus, errorThrown) {
alert(xhr.responseText);
alert(textStatus);
});
警告:使用访问控制允许来源:*会使您的API/网站易受跨站点请求伪造(CSRF)攻击。在使用此代码之前,请确保您了解风险。
如果您使用的是PHP,这很容易解决。只需在处理请求的PHP页面的开头添加以下脚本:
<?php header('Access-Control-Allow-Origin: *'); ?>
如果您使用的是Node red,则必须通过取消注释以下行,在Node red/settings.js文件中允许CORS:
// 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;你必须先安装烧瓶胸衣
pip install -U flask-cors
然后在应用程序中包含Flask cors包。
from flask_cors import CORS
一个简单的应用程序如下所示:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"
有关详细信息,请查看Flask文档。
因为$.ajax({type:“POST”-调用OPTIONS$.post(-调用post
两者都不同。邮递员正确地调用“POST”,但当我们调用它时,它将是“OPTIONS”。
对于C#web服务-web API
请在web.config文件的<system.webServer>标记下添加以下代码。这将起作用:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
请确保您在Ajax调用中没有犯任何错误。
jQuery
$.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。
System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
Deep
在以下作为API的调查中,我使用http://example.com而不是http://myApiUrl/login从你的问题,因为这第一个工作。我想你的页面已打开http://my-site.local:8088.
注意:API和您的页面有不同的域!
你看到不同结果的原因是邮差:
set header Host=example.com(您的API)NOT设置标题原点邮递员实际上根本不使用您的网站url(您只在邮递员中键入您的API地址)-他只向API发送请求,所以他假设网站的地址与API相同(浏览器不假设这一点)
这类似于当站点和API具有相同的域时浏览器发送请求的方式(浏览器也设置了标题项Referer=http://my-site.local:8088但我在邮差身上看不到)。当未设置Origin标头时,服务器通常默认允许此类请求。
这是邮差发送请求的标准方式。但是,当您的站点和API具有不同的域时,浏览器会以不同的方式发送请求,然后CORS会发生,浏览器会自动:
sets header Host=example.com(您的API)设置标题原点=http://my-site.local:8088(您的网站)
(标头Referer的值与原点相同)。现在,在Chrome的控制台和网络选项卡中,您将看到:
当您拥有主机!=Origin这是CORS,当服务器检测到这样的请求时,它通常会默认阻止它。
当您从本地目录打开HTML内容时,Origin=null被设置,并且它会发送请求。同样的情况是,当您在<iframe>中发送请求时,如下面的代码段所示(但这里根本没有设置Host头)-通常,无论HTML规范在哪里表示不透明的起源,您都可以将其转换为origin=null。您可以在此处找到有关此的更多信息。
获取('http://example.com/api',{method:“POST”});查看chrome控制台>网络选项卡
如果您不使用简单的CORS请求,通常浏览器也会在发送主请求之前自动发送OPTIONS请求-这里有更多信息。下面的代码片段显示了它:
获取('http://example.com/api', {method:'POST',headers:{“Content Type”:“application/json”}});在chrome控制台->网络选项卡中查找“api”请求。这是OPTIONS请求(服务器不允许发送POST请求)
您可以更改服务器的配置以允许CORS请求。
下面是一个在nginx(nginx.conf文件)上打开CORS的示例配置-非常小心地为nginx设置总是/“$http_origin”,为Apache设置“*”-这将阻止CORS从任何域(在生产中,而不是使用使用api的具体页面地址)
位置~^/index\.php(/|$){...add_header“Access Control Allow Origin”“$http_Origin”始终;add_header“访问控制允许凭据”“始终为true”;if($request_method=OPTIONS){add_header'访问控制允许来源'“$http_Origin”;#请勿移除该行(用上面的外部“if”加倍)add_header'访问控制允许凭据''true';add_header'访问控制最大年龄'1728000;#缓存20天的飞行前值add_header'访问控制允许方法''GET,POST,OPTIONS';add_header'访问控制允许标头''我的第一个标头,我的第二个标头,授权,内容类型,接受,来源';add_header“内容长度”0;add_header“内容类型”“text/plain charset=UTF-8”;返回204;}}
下面是一个在Apache上打开CORS的示例配置(.htaccess文件)
# ------------------------------------------------------------------------------#|跨域Ajax请求|# ------------------------------------------------------------------------------#启用跨源Ajax请求。# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity# http://enable-cors.org/#<IfModule mod_headers.c>#标题集访问控制允许来源“*”#</IfModule>#标题集标题集访问控制允许来源“*”#标头始终将访问控制允许凭据设置为“true”访问控制允许来源“http://your-page.com:80"标头始终设置访问控制允许方法“POST、GET、OPTIONS、DELETE、PUT”标头始终设置访问控制允许标头“My First Header,My Second Header,Authorization,content type,csrf token”
解决方案和问题来源
您正在向不同的域发出XMLHttpRequest,例如:
域一:some-Domain.com域二:some-different-Domain.com
域名的这种差异触发了名为SOP(同源策略)的CORS(跨源资源共享)策略,该策略强制在Ajax、XMLHttpRequest和其他HTTP请求中使用相同的域(因此是源)。
当我通过Chrome扩展发出请求时,为什么它会起作用邮递员
客户端(大多数浏览器和开发工具)可以选择强制执行同源策略。
大多数浏览器强制执行同源策略,以防止与CSRF(跨站点请求伪造)攻击相关的问题。
Postman作为一种开发工具,在某些浏览器强制执行SOP时选择不强制执行SOP,这就是为什么您可以通过Postman发送请求,而不能使用浏览器通过JS通过XMLHttpRequest发送请求。
通过在全球范围内应用此中间件,它对我很有用:
<?php
namespace App\Http\Middleware;
use Closure;
class Cors {
public function handle($request, Closure $next) {
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', "Accept,authorization,Authorization, Content-Type");
}
}