我使用ngResource在亚马逊Web服务上调用REST API得到这个错误:

XMLHttpRequest无法加载 http://server.apiurl.com: 8000 / s /登录吗? =登录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的头文件。


当前回答

当DNS服务器设置为8.8.8.8(谷歌’s)时,我遇到过这个问题。事实上,问题出在路由器上。我的应用程序试图通过谷歌连接服务器,而不是本地连接(对于我的特定情况)。

我已经删除了8.8.8.8,这解决了这个问题。我知道CORS设置解决了这个问题,但是可能有人会遇到和我一样的问题。

其他回答

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

说到CORS,有一些注意事项。首先,它不允许通配符*,但不要在这一点上束缚我。我在什么地方读过,现在找不到那篇文章了。

如果您正在从不同的域发出请求,则需要添加允许起源标头。

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

如果您正在发出影响服务器资源的请求,如POST/PUT/PATCH,并且如果MIME类型不同于以下应用程序/x-www-form-urlencoded, multipart/form-data或text/plain,浏览器将自动发出一个pre-flight OPTIONS请求,以检查服务器是否允许这样做。

所以你的API/服务器需要相应地处理这些OPTIONS请求,你需要用适当的访问控制头进行响应,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报头很重要,在我的情况下,没有它就不能工作,我猜浏览器需要多长时间的“访问权限”是有效的信息。

此外,如果你正在使用application/json mime从不同的域发出POST请求,你还需要添加前面提到的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文档中有一个很好的例子,你也应该看看Stack Overflow的帖子。

对于那些使用带有API网关的Lambda集成代理的人,您需要配置您的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" : "*"
        }
    }
}

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>

你遇到了CORS问题。

有几种方法可以修复或解决这个问题。

关闭CORS。例如:如何在Chrome中关闭CORS 为你的浏览器使用插件 使用代理,例如nginx。示例如何设置 完成服务器的必要设置。这与您在EC2实例上加载的web服务器有关(假设这就是您所说的“Amazon web服务”)。对于特定的服务器,可以参考启用CORS网站。

更详细地说,您试图从localhost访问api.serverurl.com。这就是跨域请求的确切定义。

通过关闭它来完成你的工作(好吧,但是如果你访问其他网站,你的安全性就差了),或者你可以使用代理,让你的浏览器认为所有的请求都来自本地主机,而实际上你有一个本地服务器,然后调用远程服务器。

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


现在,根据大众的需求,更多的CORS信息-同样的美味!


绕过CORS正是为那些只是学习前端的人所展示的。 带有承诺的HTTP示例