Slim 框架上 CORS 期间的预检授权标头

Posted

技术标签:

【中文标题】Slim 框架上 CORS 期间的预检授权标头【英文标题】:Preflight authorization header during CORS on Slim framework 【发布时间】:2017-07-02 22:34:13 【问题描述】:

现在我遇到了 CORS(跨域资源共享)问题,尤其是在尝试向 slim api 发送授权时。我试图删除 jquery 上的授权标头,它就像一个魅力!但是我需要授权才能传递 api 密钥,但我不知道如何绕过预检模式(选项)。这是javascript代码。

$.ajax(
    type:'GET',
    url:baseApi+'/code/account',
    crossDomain:true,
    xhrFields:
        withCredentials:true
    ,
    beforeSend:function(xhr)
        $overlay.css('display','block');
        xhr.setRequestHeader("Authorization",boot._header);
    ,
    complete:function(xhr)
        // complete scope        
    
);

在 slim 框架上,我已将 Access-Control-Allow-Origin 设置为白名单源域 (www.example.com)。这是完整的配置

if (isset($_SERVER['HTTP_ORIGIN'])) 
    if($_SERVER['HTTP_ORIGIN'] == "http://www.example.com")
        header("Access-Control-Allow-Origin: $_SERVER['HTTP_ORIGIN']");
    
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day


if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') 

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers: Authorization, authorization, Content-Type");

这里是完整的请求和响应标头

响应标头

HTTP/1.1 404 Not Found
Date: Tue, 14 Feb 2017 14:44:34 GMT
Server: Apache/2.4.23 (Unix) OpenSSL/1.0.2h php/5.6.24 mod_perl/2.0.8-dev Perl/v5.16.3
X-Powered-By: PHP/5.6.24
Access-Control-Allow-Origin: http://www.example.com
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization, authorization
Content-Length: 514
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html;charset=UTF-8

请求标头

OPTIONS /code/account HTTP/1.1
Host: api.example.com
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://www.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Access-Control-Request-Headers: authorization
Referer: http://www.example.com/account/payout
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,id;q=0.6,ms;q=0.4
Accept: */*

我已经尝试过其他人可能的解决方案,但没有机会解决这个问题。总是显示 404 并调用了 OPTIONS 方法,而不是像它应该的那样 GET 方法。

【问题讨论】:

您共享的代码有效。 Allow-methodsAllow-headers 都在响应标头中。由于共享代码,没有生成404。 Slim 框架仍将其视为OPTIONS 方法。并且请求的端点使用GET 方法注册。在浏览器控制台OPTIONS http://api.example.com/code/account 404 (Not Found) 上检查此响应。它继续显示XMLHttpRequest cannot load http://api.example.com/code/account. Response for preflight has invalid HTTP status code 404 按照我的理解,这不是GET 请求,而是OPTIONS 请求,之后是GET 请求,因此您可能需要同时注册两者。 您最好使用中间件而不是尝试手动处理标头:github.com/tuupola/cors-middleware 我通过将 Content-Type 关键字添加到 Access-Control-Allow-Headers 来编辑您的初始问题,以使您的答案正确。它应该工作 【参考方案1】:

对于 Slim Framework 2.4 版本,我做了一个小技巧来处理 Preflight OPTIONS 请求

\Slim\Slim::registerAutoloader();

$app = new \Slim\Slim();
    if($app->request->isOptions()) 
        return true;
        break;
    
    $app->post('/authenticate', 'authenticateUser');

$app->run();

所以这将跟踪所有 OPTIONS 请求并返回 true,它对我有用。

我的 .htaccess 文件如下

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "X-Requested-With, Content-Type, Accept, Origin, Authorization"
Header add Access-Control-Allow-Methods "GET, POST, OPTIONS"

希望这会有所帮助。

【讨论】:

【参考方案2】:

经过研究和调查,我最终按照@Mika Tuupola 的建议为 Slim 使用了 CORS 中间件。但由于我使用的是 Slim v2,所以这个 repo https://github.com/palanik/CorsSlim 适合我。如果您使用的是 Slim v3,请使用我们的救星创建的这个 repo https://github.com/tuupola/cors-middleware。希望对您有所帮助!

【讨论】:

以上是关于Slim 框架上 CORS 期间的预检授权标头的主要内容,如果未能解决你的问题,请参考以下文章

Amazon S3 CORS 标头仅在 OPTIONS(预检)期间显示,而不在 GET 请求期间显示

带有授权标头的 GET 请求之前的 OPTIONS 请求在苗条框架 4 中不起作用

被 CORS 阻止:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权

被 CORS 策略阻止:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权

Laravel API cors-预检响应中的Access-Control-Allow-Headers不允许请求标头字段授权[重复]

如何使用授权标头发出 GET CORS 请求