XMLHttpRequest的访问受到CORS策略的阻止

73

当我尝试在Angular 7 Web应用程序中进行PATCH请求时,遇到了问题。 我的后端代码如下:

app.use((req, res, next) => {
    res.set({
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "*",
        "Access-Control-Allow-Headers": "'Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token'",
    });

    next();
});

在我的前端服务中,我有以下内容:
  patchEntity(ent: any, id) {
    let headers = new Headers({ 'Content-Type': '*' });
    let options = new RequestOptions({ headers: headers });
    return this.http.patch('my_url', ent).map((res: Response) => res.json());
  };

错误信息为:
Access to XMLHttpRequest at 'my_url' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

我能帮你做什么呢?谢谢。


1
Access-Control-Allow-Methods 的通配符在所有浏览器中尚未得到支持。此外,错误消息表明它返回了非200状态,因此您应该先查看为什么出错。 - user184994
1
不,只需传递实际值,即 POST、GET、OPTIONS、PATCH 以及其他您关心的值。 - user184994
请参考此帖子获取答案和解决此问题的方法: https://dev59.com/6LDla4cB1Zd3GeqP3SGQ#53528644 - Ramesh Roddam
答案部分正在慢慢填充有关如何在您喜爱的服务器上破解/禁用CORS的提示,这通常不是一个明智的做法,在这个问题的背景下也相当离题。将问题标记为“受保护”。 - Andrey Tyukin
显示剩余2条评论
13个回答

57

这个问题有两种解决方法:

  1. 暂时的前端解决方案,以便您可以测试 API 集成是否正常:

点击窗口->键入运行并按回车键->在命令窗口中复制:

chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security

这将打开一个新的“Chrome”窗口,您可以轻松地使用它。这是一个临时的解决方案。每次你都需要使用这个 Chrome 窗口。

  1. 永久的解决方案:

在后端代码中,开发人员需要在 CRUD API 调用方法上方添加一个注释 @Crossorigin。

让我知道它是否有效。


第一个临时前端解决方案运行良好,但第二个后端解决方案未达到预期效果。 - ShraOne Devade
有关此事有任何更新吗?我遇到了相同的问题,而永久解决方案对我来说并不起作用。 - Aditya Mangal
有人知道Mac的临时解决方案命令吗? - undefined

10

你遇到的错误:

跨站资源共享(CORS)策略阻止从源'http://localhost:4200'访问到地址为'my_url'的XMLHttpRequest请求:preflight请求的响应未通过访问控制检查,它没有HTTP ok状态。

我的错误:

跨站资源共享(CORS)策略阻止从源'http://localhost:4200'访问到地址为'localhost:3000/api/todo'的XMLHttpRequest请求:跨域请求仅支持协议方案:http、data、chrome、chrome-extension、https。

(即使出现了略微不同的错误,我也会回答)

现在有两个问题:

  1. 我如何解决我的问题?

答案是,在我使用的api之前加上 'http://',即 'http://localhost:3000/api/todo'。

  1. 你的错误可能是什么造成的?

答案是不能确定,但我看不到你的api url,而是出现了'my_url'(与两个错误进行比较)。我认为你可能传递了字符串而不是变量。

如果这能帮助任何人,我会很高兴。因为这让我花费了近两个小时,现在已经快到午夜了。


3
在一个租户解决方案中,对我来说加上 http:// 前缀解决了问题。 - PatricNox

7

尽管我的API使用了CORS并拥有适当的标头,但我还是遇到了同样的问题。

所以对于我来说,问题在于我发起了一个不安全的请求。我正在通过http协议访问我的API,这导致了错误。

我只需更改:

http://api.example.com

转换为HTTPS协议

https://api.example.com

它修复了所有问题。


您还可以在您的网站上创建一个简单的代理,将您的请求转发到外部网站。例如,如果您正在尝试从您的网站(my-website.com)向(another-website.com)获取一些数据,并且发出了POST请求,可能会遇到cors问题,但是如果您从自己的域获取数据,则不会有问题。

以下是如何创建简单代理转发请求:https://dev59.com/PWIj5IYBdhLWcg3wWj-d#20354642

因此,您可以使用代理来发出请求:

POST https://api.example.com/event/create

你需要发起请求到

POST https://my-website.com/api/event/create

我知道这会增加一些工作量,有时你可能没有能力去做,但这绝对会防止你出现跨域问题。


6

在 Node 中使用此代码

    app.use(function (req, res, next) {
    //Enabling CORS
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, 
    Accept, x-client-key, x-client-token, x-client-secret, Authorization");
      next();
    });

在Angular中,请求的方式是:

 auth(login): Promise<any> {
 return new Promise((resolve, reject) => {
   this._http.post('url:3000/api/auth/login', { ...login })
     .subscribe((response: any) => {
       resolve(response);
     });
 });
}

2
那样做没有帮助。那里没有任何东西会使OPTIONS请求得到200 OK响应。 - Quentin

2
这个问题与你的前端Angular代码无关,而是与后端相关。
请尝试在后端代码中执行以下步骤:
1. 运行命令npm install cors 2. 在主Express路由文件中添加app.use(cors())(启用所有CORS请求)
也许这样可以解决你的问题。
参考链接: https://expressjs.com/en/resources/middleware/cors.html

这是不足够的。请参考https://expressjs.com/en/resources/middleware/cors.html#enabling-cors-pre-flight。 - Quentin

2

我曾经遇到过相同的问题。以下代码片段在后端为我工作。后端是用express、node编写的。

app.use(function (request, response, next) {
  response.header("Access-Control-Allow-Origin", "*");
  response.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

2
那样做没有帮助。在那里没有任何东西会使OPTIONS请求得到200 OK的响应。 - Quentin

1

Firebase服务器特定问题:

在我的情况下,当我尝试访问我的URL时,我遇到了相同的以下错误。

Access to XMLHttpRequest at 'https://XXX-XXX-XXX-default-rtdb.asia-southeast1.firebasedatabase.app/' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

我用来发送此请求的代码如下:

this.http
      .put(
        "https://XXX-XXX-XXX-default-rtdb.asia-southeast1.firebasedatabase.app/",
        data
      )
      .subscribe((response) => {
        console.log(response);
      });

我尝试寻找解决方案,但没有找到确切的解决方案。无论如何,我设法找出我的错误,并且这是我的解决方案。

对于我的情况,错误是由无效的URL引起的。我应该在URL末尾发送.json,以便Firebase将其视为有效的URL。(https://firebase.google.com/docs/database/rest/start)

在我的URL后追加.json后,我的HTTP请求成功了。

this.http
      .put(
        "https://XXX-XXX-XXX-default-rtdb.asia-southeast1.firebasedatabase.app/.json",
        data
      )
      .subscribe((response) => {
        console.log(response);
      });

0

在 package.json 中添加代理或使用 Chrome 扩展程序绕过并不是真正的解决方案。请确保在注册路由之前已在服务器端启用了 CORS。下面给出的示例是基于 Node.js 和 Express.js 的。希望这能帮到你!

app.use(cors())
app.use('/posts', postRoutes)

0

针对那些在后端使用ASP.net Core的人

将以下内容添加到program.cs中

    builder.Services.AddCors(c =>
{
    c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin().AllowAnyMethod().
     AllowAnyHeader());
});

app.UseCors("AllowOrigin");

0
在我的情况下,错误是由于 service.ts 文件中缺少了 '/' 导致的。我在后端使用的是 Django。
getData(id: number): Observable<any> {
    return this.http.get<any>(`${this.APIurl}/data/${id}`);
}

所以,我在末尾添加了一个'/'。
getData(id: number): Observable<any> {
    return this.http.get<any>(`${this.APIurl}/data/${id}/`);
}

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