响应预检请求未通过访问控制检查 - 没有'Access-Control-Allow-Origin'头部

710
我在使用ngResource调用REST API时遇到了这个错误,API是在Amazon Web Services上的:

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的头信息。


1
你是在“配置服务器”还是在“亚马逊网络服务上创建REST API”? - dandavis
3
你显然没有在服务器端足够地启用CORS。请提供响应头的示例。 - charlietfl
4
不管怎样,你的负评都是错误的。他正在将文件托管在本地计算机上。无论他在后端进行什么样的配置,都没有意义。Angular 不会允许这种预检请求。 - user796446
3
谢谢您的评论,在我将浏览器安全设置关闭后,问题得以解决。 - Andre Mendes
3
但是关闭安全性只是一种牺牲安全性的丑陋权宜之计,无法解决你的问题。 - shivi
显示剩余3条评论
28个回答

1

检查请求是否发送到正确的端点。在我的Node.js项目中,我指定了错误的端点,请求将会发送到 /api/txn/12345,而正确的端点应该是 /api/txn/:txnId 而不是 /api/txn,这导致了这个错误。


1
我正在使用AWS SDK进行上传,花了一些时间在网上搜索后,我偶然发现了这个问题。感谢@lsimoneau 45581857,原来完全相同的事情也发生过。
我只需通过附加区域选项将请求URL指向我的存储桶上的区域即可解决问题。
 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });

0

只需几个简单的步骤,就可以轻松解决这个问题,无需担心任何事情。

请按照以下步骤解决:

  1. 打开 (https://www.npmjs.com/package/cors#enabling-cors-pre-flight)
  2. 进入安装页面并复制命令 npm install cors 以通过终端在 Node.js 中进行安装
  3. 通过滚动到 Simple Usage(启用所有 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
在我看来,这只适用于 Express Node 应用程序,而不适用于其他任何应用程序。 - Kube Kubow

0

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>

那没有添加任何响应头,所以它没有起作用。 - JollyRoger

0

我已经让它工作了,通过添加 OPTIONS 方法到 Access-Control-Allow-Methods

Access-Control-Allow-Methods: GET, OPTIONS

但是!这在Chrome和Firefox中可以工作,但遗憾的是在Chromium中无法工作。


只有当客户端明确发送使用 OPTIONS 作为方法的请求时(例如使用 fetch(url, {method: 'OPTIONS'})),在 Access-Control-Allow-Methods 标头中列出 OPTIONS 才有用。一般来说,在预检请求成功的情况下,不必在 Access-Control-Allow-Methods 标头中列出 OPTIONS - jub0bs
不,预检请求本质上是使用OPTIONS @jub0bs。 - Stan
@Stan,预检请求使用OPTIONS作为方法并不意味着您一定需要在CORS配置中允许OPTIONS。如果您还不确定,可以查看此CORS playground(其中未列出OPTIONS)。或者,您也可以查看Fetch标准。 - jub0bs
@jub0bs 如果在同一域内,我想不需要。否则,我猜浏览器会代表你发送选项。 - Stan
@jub0bs 另外,我能够看到它使用第一个选项发送了预先请求:https://prnt.sc/4TdbzmyZhHrX ,这就是我的意思。 - Stan
@Stan 当你运行该 playground 时,请打开控制台;它是一个跨域请求(从 https://jakearchibald.comhttps://cors-playground.deno.dev)。是的,有一个预检请求,但它的响应不需要在 Access-Control-Allow-Methods 头中列出 OPTIONS 才能成功进行预检。这就是我的观点。 - jub0bs

0

"响应预检请求未通过访问控制检查"正是问题所在:

在发出实际的GET请求之前,浏览器会检查服务是否正确配置了CORS。这是通过检查服务是否接受将要用于实际请求的方法和标头来完成的。因此,仅允许从不同来源访问服务是不够的,还必须满足其他要求。

设置标头为

Header always set Access-Control-Allow-Origin: www.example.com 
Header always set Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS 
Header always set Access-Control-Allow-Headers: Content-Type #etc...

不足以。您必须添加重写规则:

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

这篇文章写得很棒:预检响应没有HTTP的OK状态

-1

有一件非常容易被忽略的事情...

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


这可能指的是Visual Studio中的某些内容。与IISASP.NET有关?我们可能永远不会知道(原帖已经消失了 - “最后一次出现是在3年前”)。 - Peter Mortensen

-15

禁用Chrome安全性。

创建Chrome快捷方式:右键单击→属性目标。粘贴以下内容:"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="c:/chromedev"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接