【问题标题】:CORS preflight request doesn't pass access control check: It does not have HTTP ok statusCORS 预检请求未通过访问控制检查:它没有 HTTP ok 状态
【发布时间】:2020-01-14 01:00:29
【问题描述】:

我正在尝试使用授权标头向我的 Wordpress REST API 发出 GET/POST 请求,但作为响应,我得到了

预检请求未通过访问控制检查:它没有 HTTP ok 状态。

我正在使用 JWT Authentication for WP-API 进行身份验证,并尝试了互联网上几乎所有可能的选项,但没有运气。

看看我当前的 .htaccess 配置

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

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

</IfModule>

<IfModule mod_headers.c>
  Header always set X-Content-Type-Options "nosniff"
  <IfModule mod_setenvif.c>
    SetEnvIf Origin "^(http://localhost:3000)$" CORS=$0
  </IfModule>
  Header set Access-Control-Allow-Origin %{CORS}e env=CORS
  Header set Access-Control-Allow-Credentials "true" env=CORS
  Header set Access-Control-Allow-Methods "GET, POST, OPTIONS, HEAD" env=CORS
  Header set Access-Control-Allow-Headers "*" env=CORS
  Header set Access-Control-Expose-Headers "*" env=CORS
  <FilesMatch "\.(php|html)$">
  </FilesMatch>
</IfModule>

当从 axios 发出请求时出现此错误

从源“http://localhost:3000”访问“HIDDEN_SERVER_ADDRESS”处的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态。

在 PostMan 中,调用工作正常并给出了预期的结果。

【问题讨论】:

  • “在 PostMan […]” - 无关紧要,这不是 CORS 首先应用的场景。 RewriteRule ^(.*)$ $1 [R=200,L] - 此时仅尝试设置状态代码,但请求仍会传递到处理此 URL 路由的任何脚本 - 因此,如果该脚本随后发出不同的状态代码,它将简单地覆盖它。跨度>
  • 我在发送 OPTION 标头时设置 200 状态代码,以便验证我的预检请求。有什么可能的解决方案?
  • “所以我的预检请求得到了验证” - 是的,除非 - 我刚才说的……仅仅因为你在 .htaccess 中设置了状态码,并不意味着你的 PHP脚本 - 仍然使用此请求方法调用 - 可能不会覆盖它。 (例如,如果它遇到致命错误,因为缺少预期的请求数据。)

标签: php wordpress apache rest cors


【解决方案1】:

在 .htaccess 中尝试所有可能的解决方案对我来说没有帮助。因此,如果其他人在同一页面上,这里的解决方案对我有用。

将此代码放在 index.php 文件中,它会像一个魅力一样工作。

header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Methods: HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method,Access-Control-Request-Headers, Authorization");
header('Content-Type: application/json');
$method = $_SERVER['REQUEST_METHOD'];
if ($method == "OPTIONS") {
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method,Access-Control-Request-Headers, Authorization");
header("HTTP/1.1 200 OK");
die();
}

【讨论】:

  • 我不喜欢你的代码是die()。如果你删除它,它很可能仍然无法工作。
  • 因为您使用die() 终止了该进程。所以die()之后的所有东西都不会被执行。
  • 我正在开发一个无头 wordpress 应用程序,所以在我的情况下 die() 是必要的
  • 我尝试了一切,这是唯一对我有用的解决方案,谢谢。话虽如此,实际上将允许来源设置为您希望发出请求的 URL 可能是一个好主意。至少对于私有 API。
  • 我花了大约 8 个小时寻找这个。
【解决方案2】:

Azaz Khan 提供的解决方案对我有用。我搜索了它的工作原理,发现 this 关于使用 OPTIONS 方法的请求

使用跨域资源共享 (CORS) 时,会自动发送带有 OPTIONS 的预检请求,因此目标资源会以可接受的参数进行响应。在正常的 Web 开发场景中,不需要进行 OPTION 调用,因为它是由浏览器发出的。

所以我认为在身份验证请求之前,已经触发了带有 OPTIONS 方法的请求,但是后端 API 没有返回 200 OK 响应。对我来说,后端发回了一个 PHP 错误,可能是 404 http 错误,我没有检查,但是使用这段代码,我确信 API 会因为退出而返回 200 OK 响应:

<?php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json; charset=UTF-8');
header('Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE');
header('Access-Control-Allow-Headers: Content-Type,Access-Control-Allow-Headers,Authorization,X-Requested-With');

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
  header('HTTP/1.1 200 OK');
  exit();
}

【讨论】:

    猜你喜欢
    • 2020-11-12
    • 2020-06-06
    • 1970-01-01
    • 2020-02-11
    • 2019-07-07
    • 2021-03-17
    • 2021-07-11
    • 2019-08-09
    • 2021-09-06
    相关资源
    最近更新 更多