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

时间:2016-02-23 21:37:07

标签: javascript ajax http cors http-status-code-405

我使用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,我不知道还有什么办法可以解决这个问题。我甚至将服务器配置为接受来自localhost的标头。

24 个答案:

答案 0 :(得分:191)

您正在遇到CORS问题。

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

  1. 关闭CORS。例如:how to turn off cors in chrome
  2. Use a plugin for your browser
  3. 使用nginx等代理。 example of how to set up
  4. 更详细地说,您正试图从localhost访问api.serverurl.com。这是跨域请求的确切定义。

    要么关闭它只是为了让你的工作完成(好吧,如果你访问其他网站并且只是踢开罐头就给你带来了不好的安全性)你可以使用代理让你的浏览器认为所有请求都来自本地主机,当你真的有本地服务器,然后调用远程服务器。

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

    现在受欢迎的需求,100% more CORS info ......同样很棒的味道!

    对于downvoters来说......绕过CORS正是那些只是学习前端的人所展示的。 https://codecraft.tv/courses/angular/http/http-with-promises/

答案 1 :(得分:138)

我的“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');

答案 2 :(得分:37)

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

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


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

[EnableCors("AllowAllHeaders")]

并将<script> $(document).ready(function () { $(".ui-datepicker-current").datepicker({ showOn: "button", buttonImageOnly: true, buttonImage: 'http://reginasoccer.com/images/calendar.gif' }); $('.ui-button').click(function () { if ($(this).is(':checked')) { $(".ui-datepicker-current").datepicker({ beforeShowDay: $.datepicker.noWeekends }) } else { $(".ui-datepicker-current").datepicker({ beforeShowDay: $.datepicker.noWeekends }) } }); }); </script> <div> <asp:CheckBox ID="chkWeekend" CssClass="ui-button" runat="server" /> <asp:TextBox ID="txtSelectedDate" CssClass="ui-datepicker-current" runat="server"></asp:TextBox> </div> 放在控制器上。

答案 3 :(得分:14)

  

JavaScript XMLHttpRequest 获取遵循同源策略。所以,   使用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

答案 4 :(得分:8)

如果您正在撰写 chrome-extension

您必须在manifest.json域中添加权限。

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

答案 5 :(得分:6)

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

如果要从其他域发出请求,则需要添加允许来源标头。 Access-Control-Allow-Origin: www.other.com

如果您发出的请求会影响POST / PUT / PATCH之类的服务器资源,并且如果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标头很重要,在我的情况下,没有它就无法使用,我猜浏览器需要“访问权限”有效期的信息。

此外,如果您正在制作来自不同域的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标头都应在响应中给出,以使其起作用。

this link上的MDN文档中有一个很好的例子,您还应该查看this SO post

答案 6 :(得分:5)

如果您偶然使用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';

用这个全部帖子,等等,都可以正常工作。

答案 7 :(得分:4)

在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: *");
...

答案 8 :(得分:4)

对于python flask服务器,您可以使用flask-cors插件启用跨域请求。

请参阅:https://flask-cors.readthedocs.io/en/latest/

答案 9 :(得分:3)

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

npm i cors

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

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

答案 10 :(得分:2)

在我的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]

答案 11 :(得分:2)

对于那些使用 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" : "*"
           }
     }
}

答案 12 :(得分:2)

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

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

答案 13 :(得分:2)

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

答案 14 :(得分:1)

enter image description here

使用 API 网关中的 Cors 选项,我使用了上面显示的以下设置

另外,请注意,您的函数必须返回 HTTP 状态 200 以响应 OPTIONS 请求,否则 CORS 也会失败。

答案 15 :(得分:1)

对于使用Api Gateway的HTTP API和代理路由的任何人 ANY / {proxy +}

您需要明确定义路由方法,以便CORS正常工作。

enter image description here

希望这在AWS Docs for Configuring CORS for an HTTP API

中更明确

在与AWS Support进行2小时的通话后,他们与一位提出此建议的高级HTTP API开发人员进行了交流。

希望这篇文章可以为使用Api Gateway HTTP API的人员节省一些时间和精力。

答案 16 :(得分:1)

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

从webapps / geoserver / WEB-INF / web.xml取消注释以下<filter><filter-mapping>

<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>

答案 17 :(得分: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 });

答案 18 :(得分:1)

当DNS服务器设置为8.8.8.8(google&#39; s)时,我遇到了这个问题。实际上,问题出在路由器上,我的应用程序试图通过谷歌连接服务器,而不是本地(对于我的特定情况)。我已经删除了8.8.8.8,这解决了这个问题。 我知道这个问题通过CORS设置解决了,但也许有人会遇到和我一样的麻烦

答案 19 :(得分:0)

我认为从Chrome中禁用CORS不是好方法,因为如果你在离子中使用它,当然在移动构建中,问题会再次引发。

最好在你的后端修复。

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

  • 标题(&#39; Access-Control-Allow-Origin:*&#39;);
  • 标题(&#39;标题集设置Access-Control-Allow-Headers:&#34; Origin,X-Requested-With,Content-Type,Accept&#34;&#39;);

如果API表现为GET和POST两者,那么也在标题中设置 -

  

if($ _SERVER [&#39; REQUEST_METHOD&#39;] ==&#39; OPTIONS&#39;){if   (isset($ _ SERVER [&#39; HTTP_ACCESS_CONTROL_REQUEST_METHOD&#39;]))         标题(&#34;访问控制 - 允许 - 方法:GET,POST,OPTIONS&#34;);
    if(isset($ _ SERVER [&#39; HTTP_ACCESS_CONTROL_REQUEST_HEADERS&#39;]))         报头(&#34;接入控制允许接头:
  {$ _SERVER [&#39; HTTP_ACCESS_CONTROL_REQUEST_HEADERS&#39;]}&#34);出口(0); }

答案 20 :(得分:-1)

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

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

答案 21 :(得分:-2)

很容易错过的东西......

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

答案 22 :(得分:-6)

请重新启动您的 chrome/web 浏览器并再次检查 API 请求。它对我有用。

答案 23 :(得分:-7)

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