我试图从HP Alm的REST API中获取一些数据。它适用于小卷曲脚本 - 我得到了我的数据。
现在使用JavaScript,fetch和ES6(或多或少)似乎是一个更大的问题。我不断收到此错误消息:
无法加载Fetch API。对预检请求的响应不是 通过访问控制检查:否'访问控制 - 允许 - 来源'标题是 出现在请求的资源上。起源' http://127.0.0.1:3000'是 因此不允许访问。响应具有HTTP状态代码501。 如果不透明响应满足您的需求,请将请求的模式设置为 '无CORS'在禁用CORS的情况下获取资源。
我理解这是因为我试图从我的localhost中获取该数据,解决方案应该使用CORS。现在我以为我确实这样做了,但不管怎么说它要么忽略我在标题中写的内容,要么问题是别的什么?
那么,是否存在实施问题?我做错了吗?不幸的是,我无法检查服务器日志。我真的有点卡在这里。
function performSignIn() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
headers.append('GET', 'POST', 'OPTIONS');
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(sign_in, {
//mode: 'no-cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed : ' + error.message));
}
我正在使用Chrome。我也尝试使用Chrome CORS插件,但后来又收到了另一条错误消息:
' Access-Control-Allow-Origin'响应中的标头 不能是通配符' *'当请求的凭据模式是 '包括&#39 ;.起源' http://127.0.0.1:3000'因此是不允许的 访问。由...发起的请求的凭据模式 XMLHttpRequest由withCredentials属性控制。
答案 0 :(得分:407)
这个答案涵盖了很多方面,因此它分为三个部分:
如何使用CORS代理绕过“No Access-Control-Allow-Origin标头”问题
如果您不控制服务器,您的前端JavaScript代码正在向其发送请求,而该服务器的响应问题只是缺少必要的Access-Control-Allow-Origin
标头,您仍然可以获取通过CORS代理提出请求。为了说明它是如何工作的,首先是一些不使用CORS代理的代码:
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))

catch
块被点击的原因是,浏览器阻止该代码访问从https://example.com
返回的响应。浏览器这样做的原因是,响应缺少Access-Control-Allow-Origin
响应标头。
现在,这是完全相同的示例,但只是添加了CORS代理:
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))

注意:如果https://cors-anywhere.herokuapp.com在您尝试时已关闭或不可用,请参阅下文,了解如何在Heroku中部署您自己的CORS Anywhere服务器3分钟。
上面的第二个代码段可以成功访问响应,因为获取请求URL并将其更改为https://cors-anywhere.herokuapp.com/https://example.com - 只需在其前面加上代理URL - 导致请求通过该代理进行,然后:
https://example.com
。https://example.com
的回复。Access-Control-Allow-Origin
标题添加到回复中。然后,浏览器允许前端代码访问响应,因为带有Access-Control-Allow-Origin
响应头的响应是浏览器看到的。
您可以使用https://github.com/Rob--W/cors-anywhere/中的代码轻松运行自己的代理 您还可以使用5个命令轻松地将自己的代理部署到Heroku,仅需2-3分钟:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
运行这些命令后,您最终将拥有自己运行的CORS Anywhere服务器,例如https://cryptic-headland-94862.herokuapp.com/。因此,不要在您的请求网址前加https://cors-anywhere.herokuapp.com
前缀,而是在其前面加上您自己实例的网址;例如,https://cryptic-headland-94862.herokuapp.com/https://example.com。
因此,如果你去尝试使用https://cors-anywhere.herokuapp.com,你会发现它已经失效(它有时会是这样),然后考虑获得一个Heroku帐户(如果你还没有)并花2或3分钟完成上述步骤,在Heroku上部署自己的CORS Anywhere服务器。
无论您是自己运行还是使用https://cors-anywhere.herokuapp.com或其他开放代理,即使请求是触发浏览器执行CORS预检OPTIONS
请求的解决方案,此解决方案仍然有效 - 因为例如,代理还会发回预检成功所需的Access-Control-Allow-Headers
和Access-Control-Allow-Methods
标头。
如何避免CORS预检
问题中的代码会触发CORS预检 - 因为它会发送Authorization
标题。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
即使没有,Content-Type: application/json
标题也会触发预检。
“预检”是什么意思:在浏览器尝试问题代码中的POST
之前,它会首先向服务器发送OPTIONS
请求,以确定服务器是否选择了 - 接收包含POST
和Authorization
标题的跨源Content-Type: application/json
。
使用小卷曲脚本可以很好地工作 - 我得到了我的数据。
要使用curl
进行正确测试,您需要模拟浏览器发送的预检OPTIONS
请求:
curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization' \
"https://the.sign_in.url"
...将https://the.sign_in.url
替换为您的实际sign_in
网址。
浏览器需要从OPTIONS
请求中看到的响应必须包含以下标题:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
如果OPTIONS
响应不包含这些标头,那么浏览器就会停在那里,甚至不会尝试发送POST
请求。此外,响应的HTTP状态代码必须是2xx(通常为200或204)。如果是任何其他状态代码,浏览器将停在那里。
问题中的服务器正在使用501状态代码响应OPTIONS
请求,这显然意味着它正在尝试表明它没有实现对OPTIONS
请求的支持。在这种情况下,其他服务器通常会响应405“Method not allowed”状态代码。
如果服务器使用405或501或其他任何内容响应POST
请求,那么您永远无法从前端JavaScript代码直接向该服务器发出OPTIONS
个请求200或204或者如果没有回复那些必要的响应标题。
避免在问题中触发案件预检的方法是:
Authorization
请求标头,而是(例如)依赖嵌入在POST
请求正文中的身份验证数据或作为查询参数POST
正文拥有Content-Type: application/json
媒体类型,而是将POST
正文作为application/x-www-form-urlencoded
接受,其参数名为{{1其值为JSON数据的(或其他)如何修复“Access-Control-Allow-Origin标头不能是通配符”问题
我收到另一条错误消息:
' Access-Control-Allow-Origin'响应中的标头 不能是通配符' *'当请求的凭据模式是 '包括&#39 ;.起源' http://127.0.0.1:3000'因此是不允许的 访问。由...发起的请求的凭据模式 XMLHttpRequest由withCredentials属性控制。
对于包含凭据的请求,如果json
响应标头的值为Access-Control-Allow-Origin
,浏览器将不允许您的前端JavaScript代码访问响应。相反,该情况下的值必须与您的前端代码的原点*
完全匹配。
请参阅MDN HTTP访问控制(CORS)文章中的Credentialed requests and wildcards。
如果你控制要发送请求的服务器,那么处理这种情况的一种常用方法是配置服务器获取http://127.0.0.1:3000
请求头的值,并回显/反映回来进入Origin
响应标头的值。例如,使用nginx:
Access-Control-Allow-Origin
但这只是一个例子;其他(网络)服务器系统提供类似的方式来回显原始值。
我正在使用Chrome。我也尝试过使用Chrome CORS插件
Chrome CORS插件显然只是简单地在浏览器看到的响应中注入add_header Access-Control-Allow-Origin $http_origin
标头。如果插件更智能,它将要做的是将假的Access-Control-Allow-Origin: *
响应标头的值设置为前端JavaScript代码Access-Control-Allow-Origin
的实际来源。
因此,即使是测试,也要避免使用该插件。这只是一种分心。如果您想测试从服务器获得的响应而没有浏览器过滤它们,那么最好使用上面的http://127.0.0.1:3000
。
至于问题中curl -H
请求的前端JavaScript代码:
fetch(…)
删除这些行。 headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
标头是响应标头。您永远不想在请求中发送它们。唯一的影响就是触发浏览器进行预检。
答案 1 :(得分:49)
当客户端URL和服务器URL不匹配(包括端口号)时,会发生此错误。在这种情况下,您需要为CORS启用服务,这是跨域资源共享。
如果您正在托管Spring REST服务,那么您可以在博客文章 CORS support in Spring Framework 中找到它。
如果您使用Node.js服务器托管服务,那么
npm install cors --save
将以下行添加到您的server.js
var cors = require('cors')
app.use(cors()) // Use this after the variable declaration
答案 2 :(得分:10)
出现问题是因为您在前端添加了以下代码作为 request 标头:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
那些标头属于 响应 ,而不是请求。因此,删除它们,包括以下行:
headers.append('GET', 'POST', 'OPTIONS');
您的请求具有“ Content-Type:应用程序/ json”,因此触发了所谓的CORS预检。这导致浏览器使用OPTIONS方法发送了请求。有关详细信息,请参见CORS preflight。
因此,在您的后端中,您必须通过返回包括以下内容的响应标头来处理此预检请求:
Access-Control-Allow-Origin : http://localhost:3000
Access-Control-Allow-Credentials : true
Access-Control-Allow-Methods : GET, POST, OPTIONS
Access-Control-Allow-Headers : Origin, Content-Type, Accept
当然,实际语法取决于您用于后端的编程语言。
在您的前端,应该像这样:
function performSignIn() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
headers.append('Origin','http://localhost:3000');
fetch(sign_in, {
mode: 'cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed : ' + error.message));
}
答案 3 :(得分:4)
就我而言,我使用以下解决方案
前端或角度
post(
this.serverUrl, dataObjToPost,
{
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
}
)
后端(我使用php)
header("Access-Control-Allow-Origin: http://localhost:4200");
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header("Access-Control-Allow-Headers: Content-Type, Authorization");
$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
print_r($request);
答案 4 :(得分:1)
我知道我迟到了,但这会对某人有所帮助
CORS 问题的可能原因
fetch
方法并尝试访问跨域请求,请确保存在 mode:cors
。请参阅此linkOPTION
方法。答案 5 :(得分:0)
我正在使用Spring REST,并解决了将AllowedMethods添加到WebMvcConfigurer中的问题。
@Value( "${app.allow.origins}" )
private String allowOrigins;
@Bean
public WebMvcConfigurer corsConfigurer() {
System.out.println("allow origin: "+allowOrigins);
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
//.allowedOrigins("http://localhost")
.allowedOrigins(allowOrigins)
.allowedMethods("PUT", "DELETE","GET", "POST");
}
};
}
答案 6 :(得分:0)
只需两美分...关于如何使用CORS代理解决“无访问权限-允许-来源标头”问题
对于那些在后端使用php的人来说,部署“ CORS代理”非常简单:
创建一个名为“ no-cors.php”的文件,其内容如下:
$ URL = $ _GET ['url']; 回声json_encode(file_get_contents($ URL)); die();
在您的前端,执行以下操作:
fetch('https://example.com/no-cors.php'+'?url ='+ url) .then(response => { / Handle Response / })
答案 7 :(得分:0)
就我而言,Web服务器禁止使用“ OPTIONS”方法
检查您的Web服务器的选项方法
我正在使用“网络层”
/ www / webtier / domains / [域名] /config/fmwconfig/components/OHS/VCWeb1/httpd.conf
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^OPTIONS
RewriteRule .* . [F]
</IfModule>
更改为
<IfModule mod_rewrite.c>
RewriteEngine off
RewriteCond %{REQUEST_METHOD} ^OPTIONS
RewriteRule .* . [F]
</IfModule>
答案 8 :(得分:0)
使用dataType: 'jsonp'
对我有用。
async function get_ajax_data(){
var _reprojected_lat_lng = await $.ajax({
type: 'GET',
dataType: 'jsonp',
data: {},
url: _reprojection_url,
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR)
},
success: function (data) {
console.log(data);
// note: data is already json type, you
// just specify dataType: jsonp
return data;
}
});
} // function
答案 9 :(得分:0)
我在本地遇到此错误。 我以管理员身份运行Visual Studio,并解决了该问题。
答案 10 :(得分:0)
对于Nodejs,如果您使用的是路由器,请确保在路由器之前添加cors。否则,您仍然会收到cors错误。如下所示:
ARG
答案 11 :(得分:0)
添加mode:no-cors
可以避免在api中出现cors问题。
fetch(sign_in, {
mode: 'no-cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed : ' + error.message));
}
答案 12 :(得分:0)
使用下面的 npm 模块。这实际上挽救了生命。
<块引用>https://www.npmjs.com/package/local-cors-proxy
您收到 CORS 错误,例如如下网址
<块引用>https://www.google.co.in/search/list
成功安装后 (local-cors-proxy) 全局 npm install -g local-cors-proxy
并设置 CORS url 的代理 URL。例如下面的 CORS 问题进入本地主机。所以需要添加CORS问题域的域名和端口。
lcp --proxyUrl https://www.google.co.in --port 8010
设置成功后会生成如下所示的本地代理URL。
<块引用>http://localhost:8010/proxy
在您的项目 API 网址中使用该域名。 API 完整网址
<块引用>http://localhost:8010/proxy/search/list
在您的本地项目中获得没有 CORS 问题的响应。
答案 13 :(得分:0)
如果你的API是用asp dot net core编写的。然后请按照以下步骤操作:
安装 Microsoft.AspNetCore.Cors 包。
在 Startup.cs 的 ConfigureServices 方法中添加以下行:
services.AddCors();
在 startup.cs 的 Configure 方法中添加以下行:
app.UseCors(options =>
options.WithOrigins("http://localhost:8080")
.AllowAnyHeader()
.AllowAnyMethod());
make sure you add this before - app.UseRouting();
答案 14 :(得分:0)
发生这种情况是因为您无法从同一网站获取数据。因此,如果您在 abc.com 上,则无法从 api.abc.com 获取。保存网站政策。
解决方法如下:https://www.youtube.com/watch?v=RyH3qu3smVI&ab_channel=CoderDmitri
在你的 server.js -> 终端中安装这个包:
npm install cors
在您的代码之上:
const cors = require('cors');
app.use(cors());
这将允许来自同一域的用户立即获取数据。
答案 15 :(得分:0)
删除此:
credentials: 'include',
答案 16 :(得分:-1)
如果在MacOS的开发环境中将NodeJS / Express用作后端,将ReactJS / axios用作前端,则需要在https下运行双方。以下是它最终对我有用的东西(经过数小时的深入潜水和测试):
步骤1:创建SSL证书
只需遵循How to get HTTPS working on your local development environment in 5 minutes
中的步骤您最终将获得几个文件,以用作运行https服务器和ReactJS网站的凭据:
server.key & server.crt
您需要将它们复制到前端和后端的根文件夹中(在生产环境中,您可能考虑将它们复制到./ssh中作为后端)。
第2步:后端设置
我读到很多答案,建议使用“ cors”软件包甚至设置(“ Access-Control-Allow-Origin”,“ *”),就像说:“欢迎黑客访问我的网站”。就是这样:
import express from 'express';
const emailRouter = require('./routes/email'); // in my case, I was sending an email through a form in ReactJS
const fs = require('fs');
const https = require('https');
const app = express();
const port = 8000;
// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests
app.all('*', (req, res, next) => {
res.header("Access-Control-Allow-Origin", "https://localhost:3000");
next();
});
// Routes definition
app.use('/email', emailRouter);
// HTTPS server
const credentials = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
};
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(port, () => {
console.log(`Back-end running on port ${port}`);
});
如果要测试https是否可以正常运行,可以将httpsServer常量替换为以下常量:
https.createServer(credentials, (req: any, res: any) => {
res.writeHead(200);
res.end("hello world from SSL\n");
}).listen(port, () => {
console.log(`HTTPS server listening on port ${port}...`);
});
然后从Web浏览器访问它:https:// localhost:8000 /
第3步:前端设置
这是来自ReactJS前端的axios请求:
await axios.get(`https://localhost:8000/email/send`, {
params: {/* whatever data you want to send */ },
headers: {
'Content-Type': 'application/json',
}
})
现在,您需要使用我们已经创建的SSL凭证以https方式启动ReactJS网站。在MacOS终端中输入以下内容:
HTTPS=true SSL_CRT_FILE=server.crt SSL_KEY_FILE=server.key npm start
这时,您正在从前端的端口3000处的https连接发送请求,后端的8000端口处的https连接将接收请求。 CORS应该对此感到满意;)
答案 17 :(得分:-2)
最快的解决方法是安装moesif CORS扩展程序。
https://chrome.google.com/webstore/detail/moesif-orign-cors-changer/digfbfaphojjndkpccljibejjbppifbc?hl=en-US
安装后,在浏览器中单击它以激活扩展。确保图标的标签从“关闭”到 到“上” ; 然后刷新您的应用程序,您的API请求现在应该可以工作了! 该插件肯定解决了这个问题。但是,此修复程序仅适用于您自己的计算机。 在本地开发中,最好安装可以帮助您克服错误的插件。
答案 18 :(得分:-2)