简体   繁体   English

带有 PHP 标头的跨域请求标头 (CORS)

[英]Cross-Origin Request Headers(CORS) with PHP headers

I have a simple PHP script that I am attempting a cross-domain CORS request:我有一个简单的 PHP 脚本,我正在尝试跨域 CORS 请求:

<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: *");
...

Yet I still get the error:但我仍然收到错误:

Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers Access-Control-Allow-Headers不允许请求头字段X-Requested-With

Anything I'm missing?我缺少什么吗?

Handling CORS requests properly is a tad more involved.正确处理 CORS 请求有点复杂。 Here is a function that will respond more fully (and properly).这是一个可以更充分(和正确地)响应的函数。

/**
 *  An example CORS-compliant method.  It will allow any GET, POST, or OPTIONS requests from any
 *  origin.
 *
 *  In a production environment, you probably want to be more restrictive, but this gives you
 *  the general idea of what is involved.  For the nitty-gritty low-down, read:
 *
 *  - https://developer.mozilla.org/en/HTTP_access_control
 *  - https://fetch.spec.whatwg.org/#http-cors-protocol
 *
 */
function cors() {
    
    // Allow from any origin
    if (isset($_SERVER['HTTP_ORIGIN'])) {
        // Decide if the origin in $_SERVER['HTTP_ORIGIN'] is one
        // you want to allow, and if so:
        header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Max-Age: 86400');    // cache for 1 day
    }
    
    // Access-Control headers are received during OPTIONS requests
    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
        
        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
            // may also be using PUT, PATCH, HEAD etc
            header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
        
        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
            header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
    
        exit(0);
    }
    
    echo "You have CORS!";
}

Security Notes安全注意事项

Check the HTTP_ORIGIN header against a list of approved origins.根据批准的来源列表检查 HTTP_ORIGIN 标头。

If the origin isn't approved, then you should deny the request.如果来源未获批准,则您应该拒绝该请求。

Please read the spec.请阅读规范。

TL;DR TL; 博士

When a browser wants to execute a cross-site request it first confirms that this is okay with a "pre-flight" request to the URL.当浏览器想要执行跨站点请求时,它首先通过对 URL 的“飞行前”请求确认这是否正确。 By allowing CORS you are telling the browser that responses from this URL can be shared with other domains.通过允许 CORS,您告诉浏览器来自此 URL 的响应可以与其他域共享。

CORS does not protect your server. CORS 不保护您的服务器。 CORS attempts to protect your users by telling browsers what the restrictions should be on sharing responses with other domains. CORS 试图通过告诉浏览器与其他域共享响应的限制来保护您的用户。 Normally this kind of sharing is utterly forbidden, so CORS is a way to poke a hole in the browser's normal security policy.通常这种共享是完全禁止的,因此CORS是一种在浏览器正常安全策略中戳破洞的方法。 These holes should be as small as possible, so always check the HTTP_ORIGIN against some kind of internal list.这些漏洞应该尽可能小,所以总是根据某种内部列表检查 HTTP_ORIGIN。

There are some dangers here , especially if the data the URL serves up is normally protected.这里有一些危险,特别是如果 URL 提供的数据通常受到保护。 You are effectively allowing browser content that originated on some other server to read (and possibly manipulate) data on your server.您有效地允许源自其他服务器的浏览器内容读取(并可能操纵)您服务器上的数据。

If you are going to use CORS, please read the protocol carefully (it is quite small) and try to understand what you're doing.如果您打算使用 CORS,请仔细阅读协议(它非常小)并尝试了解您在做什么。 A reference URL is given in the code sample for that purpose.为此,代码示例中提供了一个参考 URL。

Header security标题安全

It has been observed that the HTTP_ORIGIN header is insecure, and that is true.已经观察到 HTTP_ORIGIN 标头是不安全的,这是真的。 In fact, all HTTP headers are insecure to varying meanings of the term.事实上,所有 HTTP 标头对该术语的不同含义都是不安全的。 Unless a header includes a verifiable signature/hmac, or the whole conversation is authenticated via TLS, headers are just "something the browser has told me".除非标头包含可验证的签名/hmac,或者整个对话都通过 TLS 进行身份验证,否则标头只是“浏览器告诉我的东西”。

In this case, the browser is saying "an object from domain X wants to get a response from this URL. Is that okay?"在这种情况下,浏览器会说“来自域 X 的对象想要从这个 URL 获得响应。可以吗?” The point of CORS is to be able to answer, "yes I'll allow that". CORS 的重点是能够回答“是的,我会允许”。

I got the same error, and fixed it with the following PHP in my back-end script:我遇到了同样的错误,并在我的后端脚本中使用以下 PHP 修复了它:

header('Access-Control-Allow-Origin: *');

header('Access-Control-Allow-Methods: GET, POST');

header("Access-Control-Allow-Headers: X-Requested-With");

Access-Control-Allow-Headers does not allow * as accepted value, see the Mozilla Documentation here . Access-Control-Allow-Headers不允许*作为可接受的值,请参阅此处的 Mozilla 文档。

Instead of the asterisk, you should send the accepted headers (first X-Requested-With as the error says).您应该发送接受的标头而不是星号(第一个X-Requested-With正如错误所说)。

Update:更新:

* is now accepted is Access-Control-Allow-Headers . *现在接受的是Access-Control-Allow-Headers

According to MDN Web Docs 2021 :根据MDN Web Docs 2021

The value * only counts as a special wildcard value for requests without credentials (requests without HTTP cookies or HTTP authentication information).对于没有凭据的请求(没有 HTTP cookie 或 HTTP 身份验证信息的请求),值*仅算作特殊的通配符值。 In requests with credentials, it is treated as the literal header name * without special semantics.在带有凭证的请求中,它被视为没有特殊语义的文字头名称* Note that the Authorization header can't be wildcarded and always needs to be listed explicitly.请注意, Authorization 标头不能使用通配符,并且始终需要明确列出。

Many description internet-wide don't mention that specifying Access-Control-Allow-Origin is not enough.互联网上的许多描述都没有提到指定Access-Control-Allow-Origin是不够的。 Here is a complete example that works for me:这是一个对我有用的完整示例:

<?php
    if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: POST, GET, DELETE, PUT, PATCH, OPTIONS');
        header('Access-Control-Allow-Headers: token, Content-Type');
        header('Access-Control-Max-Age: 1728000');
        header('Content-Length: 0');
        header('Content-Type: text/plain');
        die();
    }

    header('Access-Control-Allow-Origin: *');
    header('Content-Type: application/json');

    $ret = [
        'result' => 'OK',
    ];
    print json_encode($ret);

I've simply managed to get dropzone and other plugin to work with this fix (angularjs + php backend)我只是设法让 dropzone 和其他插件与此修复程序一起使用(angularjs + php 后端)

 header('Access-Control-Allow-Origin: *'); 
    header("Access-Control-Allow-Credentials: true");
    header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
    header('Access-Control-Max-Age: 1000');
    header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');

add this in your upload.php or where you would send your request (for example if you have upload.html and you need to attach the files to upload.php, then copy and paste these 4 lines).将此添加到您的 upload.php 或您将发送请求的位置(例如,如果您有 upload.html 并且您需要将文件附加到 upload.php,然后复制并粘贴这 4 行)。 Also if you're using CORS plugins/addons in chrome/mozilla be sure to toggle them more than one time,in order for CORS to be enabled此外,如果您在 chrome/mozilla 中使用 CORS 插件/插件,请确保多次切换它们,以便启用 CORS

If you want to create a CORS service from PHP, you can use this code as the first step in your file that handles the requests:如果要从 PHP 创建 CORS 服务,可以将此代码用作处理请求的文件中的第一步:

// Allow from any origin
if(isset($_SERVER["HTTP_ORIGIN"]))
{
    // You can decide if the origin in $_SERVER['HTTP_ORIGIN'] is something you want to allow, or as we do here, just allow all
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
}
else
{
    //No HTTP_ORIGIN set, so we allow any. You can disallow if needed here
    header("Access-Control-Allow-Origin: *");
}

header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 600");    // cache for 10 minutes

if($_SERVER["REQUEST_METHOD"] == "OPTIONS")
{
    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]))
        header("Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT"); //Make sure you remove those you do not want to support

    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]))
        header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

    //Just exit with 200 OK with the above headers for OPTIONS method
    exit(0);
}
//From here, handle the request as it is ok

CORS can become a headache, if we do not correctly understand its functioning.如果我们没有正确理解 CORS 的功能,它可能会让人头疼。 I use them in PHP and they work without problems.我在 PHP 中使用它们,它们可以正常工作。 reference here参考这里

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 1000");
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding");
header("Access-Control-Allow-Methods: PUT, POST, GET, OPTIONS, DELETE");

当使用 angular 4 作为客户端和 PHP 作为服务器端时,这些代码对我来说很有效。

header("Access-Control-Allow-Origin: *");

this should work这应该有效

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding");

add this code in .htaccess.htaccess 中添加此代码

add custom authentication key's in header like app_key,auth_key..etc在标题中添加自定义身份验证密钥,如 app_key、auth_key.. 等

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers: "customKey1,customKey2, headers, Origin, X-Requested-With, Content-Type, Accept, Authorization"

In Windows, paste this command in run window just for time being to test the code在 Windows 中,将此命令粘贴到运行窗口中只是为了测试代码

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM