对预检请求的响应未通过访问控制检查


456

我在使用ngResource调用Amazon Web Services上的REST API时遇到此错误:

XMLHttpRequest无法加载 http://server.apiurl.com:8000/s/login?login=facebook。对预检请求的响应未通过访问控制检查:在所请求的资源上不存在“ Access-Control-Allow-Origin”标头。因此,不允许访问源“ http:// localhost ”。 错误405

服务:

socialMarkt.factory('loginService', ['$resource', function($resource){    
    var apiAddress = "http://server.apiurl.com:8000/s/login/";
    return $resource(apiAddress, { login:"facebook", access_token: "@access_token" ,facebook_id: "@facebook_id" }, {
                getUser: {method:'POST'}
            });
}]);

控制器:

[...]
loginService.getUser(JSON.stringify(fbObj)),
                function(data){
                    console.log(data);
                },
                function(result) {
                    console.error('Error', result.status);
                }
[...]

我正在使用Chrome,但我不知道该怎么做才能解决此问题。我什至将服务器配置为接受origin的标头localhost


困惑:您是“配置服务器”还是“亚马逊网络服务上的REST API”?
dandavis '16

3
您显然还没有做足够的事情来在服务器端启用CORS。发布响应标头示例
charlietfl 2016年

4
无论哪种方式,您的否决票都是错误的。他将文件托管在本地计算机上。他在后端执行哪种配置都没关系。Angular不允许进行此预飞行。
E. Maggini

3
Thx的评论,当我将浏览器设置为安全性时,它起作用了
Andre Mendes

1
@Andre但是关闭安全性只是一个丑陋的解决方法,您会在安全性上妥协,无法解决您的问题...
shivi

Answers:


240

您遇到了CORS问题。

有几种方法可以解决此问题。

  1. 关闭CORS。例如:如何关闭Chrome中的cors
  2. 使用浏览器插件
  3. 使用代理,例如nginx。如何设置的例子
  4. 完成服务器的必要设置。这更多是您已在EC2实例上加载的Web服务器的一个因素(假设这就是您所说的“ Amazon Web Service”的意思)。对于您的特定服务器,您可以参考启用CORS网站。

更详细地说,您正在尝试从本地主机访问api.serverurl.com。这是跨域请求的确切定义。

通过关闭它来完成您的工作(确定,如果您访问其他站点并给您带来安全隐患,那么您可以使用代理)使您的浏览器认为所有请求都来自本地主机。确实,您有本地服务器,然后再调用远程服务器。

因此api.serverurl.com可能会变成localhost:8000 / api,而您的本地nginx或其他代理将发送到正确的目的地。


现在,由于受欢迎的需求,CORS信息增加了100%


对于不愿花钱的人……绕过CORS正是那些仅仅学习前端的人所看到的。 https://codecraft.tv/courses/angular/http/http-with-promises/


773
遗漏了正确实施CORS的明显方法之一
charlietfl 2016年

40
投票很容易。我的朋友,自己冒险不太容易。所有这些工作完全在开发环境中进行。
E.

3
它确实有效。我添加了标志以禁用Web安全性。为了发展是好的。
Andre Mendes

15
@charlietfl怎么样?
GreenAsJade

3
谢谢你救了我的日子。仅使用第一个选项:C:\ Program Files(x86)\ Google \ Chrome \ Application> chrome.exe --user-data-dir =“ C:\ Chrome开发者会话” --disable-web-security。来自:stackoverflow.com/questions/3102819/…–
Harsimer

169

我的“ API服务器”是一个PHP应用程序,因此为了解决此问题,我找到了以下解决方案:

将行放在index.php中

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');

3
我同意,尽管复制这些行时要小心,但一定要修改方法和原点,这比公认的答案要好。
阿米尔·萨凡德

11
将其放在Angular 6项目中的哪里?
whatthefish

@CodyBugstein和whatthefish放在任何输出之前
Garet Claborn

当我添加仅某些服务器所需的标头时,我的客户端应用程序停止工作。如果请求中包含任何自定义标头,则它们需要在中列出Access-Control-Allow-Headers
z0r19年

46

在AspNetCore Web API中,通过添加“ Microsoft.AspNetCore.Cors”(版本1.1.1)并在Startup.cs上添加了以下更改来解决此问题。

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddCors(options =>
    {
          options.AddPolicy("AllowAllHeaders",
                builder =>
            {
                    builder.AllowAnyOrigin()
                           .AllowAnyHeader()
                           .AllowAnyMethod();
                });
    });
    .
    .
    .
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

然后戴上[EnableCors("AllowAllHeaders")]控制器。


17
如果您要构建跨站点脚本漏洞,这是一个很好的答案!请永远不要这样做!指定您可以访问的域,以避免安全问题。CORS在那里是有原因的。
paqogomez

2
为了使它更清晰@paqogomez,请在您的ConfigureServices方法中:services.AddCors(options => {options.AddPolicy(“ AllowSpecificOrigin”,builder => {builder.WithOrigins(“ localhost”).AllowAnyOrigin().AllowAnyHeader())。 AllowAnyMethod();});}); 并在您的Configure方法中:app.UseCors(“ AllowSpecificOrigin”);
弗朗西斯科·特纳

28

关于CORS,有一些警告。首先,它不允许使用通配符,*但不要让我受此限制,因为我已经在某处阅读过它,现在找不到该文章。

如果要从其他域发出请求,则需要添加允许来源标头。

 Access-Control-Allow-Origin: www.other.com 

如果你正在影响服务器资源,如POST / PUT /补丁,如果MIME类型是比下面的不同要求application/x-www-form-urlencodedmultipart/form-datatext/plain浏览器会自动进行飞行前的OPTIONS请求来检查与服务器是否会允许它。

因此,您的API /服务器需要相应地处理这些OPTIONS请求,您需要以适当的方式进行响应,access control headers并且http响应状态代码必须为200

标头应该是这样的,根据您的需要进行调整:

   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

max-age标头很重要,在我的情况下,没有它就无法工作,我想浏览器需要“访问权限”有效期的信息。

另外,如果您要从其他域发出例如mime 的POST请求,则application/json还需要添加前面提到的allow origin标头,因此如下所示:

   Access-Control-Allow-Origin: www.other.com 
   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

当预检成功并获得所有所需信息后,您的实际请求将被提出。

一般而言,Access-Control在初始或飞行前请求中请求的任何标头都应在响应中给出,以使其起作用。

此链接的MDN文档中有一个很好的示例,您还应该查看此SO帖子。


1
这是Mozilla的文章,内容涉及如何不能将通配符用于cors来源: 链接 因此,这显然仅在使用凭据时适用(如果我正确理解的话)
Helzgate

我使用通配符并提交了承载令牌来授权请求​​,该请求工作正常,因此不确定我上面提供的链接是关于凭据的。我的问题是,在.Net Core中建立我的CORS策略时,我没有添加.AllowCredentials()。添加后.AllowCredentials()一切正常。
Helzgate

15

JavaScript XMLHttpRequestFetch遵循同源策略。因此,使用XMLHttpRequest或Fetch的Web应用程序只能向其自己的域发出HTTP请求。

来源:https : //developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

您必须从服务器端发送Access-Control-Allow-Origin:* HTTP标头。

如果将Apache用作HTTP服务器,则可以将其添加到Apache配置文件中,如下所示:

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
</IfModule>

默认情况下,Apache中启用了Mod_headers,但是,您可能需要通过运行以下命令来确保已启用:

 a2enmod headers

在哪里可以找到我的Apache配置文件?
Shubham Arya '18

Linux Debian上的@ShubhamArya默认位置为:/etc/apache2/apache2.conf
Tadej '18

在Windows的哪里可以找到它?
Shubham Arya

10

如果您正在编写chrome扩展名

您必须manifest.json为您的域添加权限。

"permissions": [
   "http://example.com/*",
   "https://example.com/*"
]

1
还要检查您是否具有www前缀
Vlas Bashynskyi

8

如果您偶然使用IIS服务器。您可以在HTTP请求标头选项中的标头下方设置。

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

与此所有帖子,获取等,将正常工作。



5

在PHP中,您可以添加标题:

<?php
header ("Access-Control-Allow-Origin: *");
header ("Access-Control-Expose-Headers: Content-Length, X-JSON");
header ("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header ("Access-Control-Allow-Headers: *");
...

谢谢,对我有用!在测试和生产环境中。甚至使用https://
Jose Seie

1
@atiruz感谢您的解决方案。当我添加线路时,此工程有效header ("Access-Control-Expose-Headers: Content-Length, X-JSON");
Silambarasan RD

5

要解决Node JS应用程序中的跨域请求问题:

npm i cors

只需将下面的行添加到 app.js

let cors = require('cors')
app.use(cors())

3
这仅适用于快速js应用程序,不适用于所有节点应用程序
DrCord

3

在我的Apache VirtualHost配置文件中,添加了以下几行:

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

3

对于那些正在使用Lambda集成代理和API网关的用户。您需要像直接向其提交请求一样配置lambda函数,这意味着该函数应正确设置响应头。(如果您使用的是自定义lambda函数,则将由API网关处理。)

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}

1
我也想提一下,并提到一个我认为AWS文档中没有的大难题。假设您使用API​​网关代理lambda函数,并且在该lambda函数中使用了一些API。如果该API返回非200成功成功代码,并且您未在API网关的方法响应中添加非200成功代码,则您将收到错误消息,并且看不到成功响应。例如:Sendgrid和Twilio具有非200的成功代码。
Stephen Tetreault,

3

我认为从Chrome禁用CORS并不是一种好方法,因为如果您将其用于离子系统,则肯定会在Mobile Build中出现。

因此最好在后端修复。

首先,在In标头中,您需要设置-

  • header('Access-Control-Allow-Origin:*');
  • header('Header set Access-Control-Allow-Headers:“ Origin,X-Requested-With,Content-Type,Accept”');

而且如果API的行为均与GET和POST相同,则还可以在标头中设置-

if($ _SERVER ['REQUEST_METHOD'] =='OPTIONS'){if(isset($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))header(“ Access-Control-Allow-Methods:GET,POST,OPTIONS”);
if(isset($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))标头(“访问控制权限标头:
{$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}”); 退出(0); }


3

导致此错误的一个很常见的原因可能是主机API已将请求映射到http方法(例如PUT),而API客户端正在使用其他http方法(例如POST或GET)调用API


我在服务器中正确实现了CORS,但是我忘记添加PUT方法了
fguillen

3

我们的团队偶尔会使用Vue,axios和C#WebApi看到这种情况。在您要命中的端点上添加路由属性可以为我们解决此问题。

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }

我们不太确定为什么。大声笑。如果有人让我知道!
w00ngy

1

当DNS服务器设置为8.8.8.8(谷歌的)时,我遇到了这个问题。实际上,问题出在路由器上,我的应用程序尝试通过Google而不是本地与服务器连接(对于我的特定情况)。我删除了8.8.8.8,这解决了问题。我知道可以通过CORS设置解决此问题,但也许有人会遇到与我相同的麻烦


1

在花了一些时间在线搜索之后,我偶然发现了这个线程,因此我正在使用AWS sdk进行上传。感谢@lsimoneau 45581857,事实证明发生了同样的事情。我只是通过附加region选项将我的请求Url指向了我的存储桶上的区域,它就起作用了。

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });

0

GeoServer的独立发行版包括Jetty应用程序服务器。启用跨域资源共享(CORS),以允许您自己域外的JavaScript应用程序使用GeoServer。

取消以下<filter>,并<filter-mapping>从webapps /下的GeoServer / WEB-INF / web.xml文件:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

这并没有增加antyhing到响应头,所以也没工作
JollyRoger

1
没有使用GeoServer,但此剪辑帮助我了解了应在接听电话的应用程序上使用的设置。
马特·费尔扎尼

0

只需几个步骤即可轻松解决此问题,而无需担心任何事情。请按照以下步骤解决。

  1. 打开(https://www.npmjs.com/package/cors#enabling-cors-pre-flight
  2. 转到安装并复制命令npm install cors以通过节点终端进行安装
  3. 通过滚动转到“简单用法(启用所有CORS请求)”,然后将完整的声明复制并粘贴到您的项目中并运行它……这将确保工作正常。.复制注释代码,并将其粘贴到您的app.js或其他任何文件中项目并尝试..这将起作用。这将解锁每个跨源资源共享。.以便我们可以在服务之间切换供您使用

1
var express = require('express')var cors = require('cors')var app = express()app.use(cors())app.get('/ products /:id',function(req,res, next){res.json({msg:'这对所有来源都启用了CORS!'})})app.listen(80,function(){console.log('已启用CORS的Web服务器侦听端口80' )})
Rahul sah

-1

很容易错过的东西...

在解决方案资源管理器中,右键单击api-project。在属性窗口中,将“匿名身份验证”设置为“已启用”!


-8

禁用Chrome安全性。右键单击->属性->目标,创建Chrome快捷方式,然后粘贴“ C:\ Program Files(x86)\ Google \ Chrome \ Application \ chrome.exe” --disable-web-security --user -data-dir =“ c:/ chromedev”

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.