401重定向神奇地导致302重定向

时间:2012-11-20 23:22:23

标签: php redirect header laravel

我正在使用Redirect类将未登录的用户发送到登录页面,其中包含 401 状态代码:

return Redirect::to('login', 401);

这会发送正确的位置标头,但状态代码设置为 302


我一直跟踪到

中的基础Response
  

laravel /供应商/ Symfony的/组件/ HttpFoundation / Response.php

它正在呼唤:

$this->setStatusCode($status);

使用正确的 401 代码。


我也试过转储对象:

var_dump( Redirect::to('login', 401)->foundation );

我可以看到受保护的statusCode属性已正确设置为 401


但是,生成的响应的HTTP状态代码设置为 302

是什么给出的?我使用它错了吗?


P.S。我也是posted this on Laravel's forums,但无济于事。

4 个答案:

答案 0 :(得分:4)

这不是因为laravel,你可以用(Windows中的PHP 5.4)重现这个:

<?php
header("HTTP/1.1 401 Unauthorized");
header("Location: http://www.google.com");

看来php将其设置为302:

$ php-cgi "test.php"
Status: 302 Moved Temporarily
Location: http://www.google.com
Content-type: text/html; charset=UTF-8

在PHP源代码main / SAPI.C中:

} else if (!STRCASECMP(header_line, "Location")) {
    if ((SG(sapi_headers).http_response_code < 300 ||
        SG(sapi_headers).http_response_code > 307) &&
        SG(sapi_headers).http_response_code != 201) {
        /* Return a Found Redirect if one is not already specified */
        if (http_response_code) { /* user specified redirect code */
            sapi_update_response_code(http_response_code TSRMLS_CC);
        } else if (SG(request_info).proto_num > 1000 && 
           SG(request_info).request_method && 
           strcmp(SG(request_info).request_method, "HEAD") &&
           strcmp(SG(request_info).request_method, "GET")) {
            sapi_update_response_code(303 TSRMLS_CC);
        } else {
            sapi_update_response_code(302 TSRMLS_CC);
        }
    }

正如您所看到的,当header() "Location" <?php header("Location: http://www.google.com"); header("HTTP/1.1 401 Unauthorized"); 时,http状态代码被修改为302

如果你这样做,你可以使它工作:

$ php-cgi "test.php"
Status: 401 Unauthorized
Location: http://www.google.com
Content-type: text/html; charset=UTF-8

这将给出:

{{1}}

但是laravel在设置状态后设置位置,因此无论如何状态都会设置回302。但这是一个没有实际意义的问题,即使您使用位置标题成功将状态设置为401,浏览器也不会重定向。

答案 1 :(得分:4)

浏览器不允许你这样做;您无法使用401重定向。

答案 2 :(得分:1)

我跟着它走得更远......直到public function sendHeaders() laravel/vendor/Symfony/Component/HttpFoundation/Response.php ...它产生最终状态标题

   // status
    Header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText));

......当然还是401。

然后它恍然大悟。 您无法使用401 重定向,这是一个ClientError。

(同样isRedirect文件中所述的Response.php测试也会失败。mod_php会在您发送Location后立即将其修复为302(因为默认情况下状态是200,所以需要更新.PHP不会检查它是否已经更新为其他内容。)

答案 3 :(得分:0)

正如其他人所指出的,没有像401重定向这样的东西。我迷上这个原因的原因是I need non-AJAX users to be redirected,但是AJAX requests should get a 401


如果你发现自己处于类似情况,这就是我最终使用的内容:

return Request::ajax() ?
         Response::make('', 401, array('HTTP/1.1 401 Unauthorized')) :
         Redirect::to('login', 302);

这使用Laravel的方法来处理标题。


如果您使用的是vanilla PHP,请使用:

$is_ajax_request = ! empty( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';

$is_ajax_request ?
    header('HTTP/1.1 401 Unauthorized') :
    header('Location: http://site.com/login');

exit;