5

我正在使用Redirect该类将未登录的用户发送到登录页面,并带有401状态代码:

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

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


我一直追踪到基Response

laravel/vendor/Symfony/Component/HttpFoundation/Response.php

它正在调用:

$this->setStatusCode($status);

使用正确的401代码。


我也尝试转储对象:

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

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


尽管如此,生成的响应的 HTTP 状态代码仍设置为302

是什么赋予了?我用错了吗?


PS我也在Laravel 的论坛上发布了这个,但无济于事。

4

4 回答 4

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",http 状态码被修改为 302

如果你反过来做,你可以让它工作:

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

这将给出:

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

但是laravel在设置状态后设置位置,所以状态无论如何都设置回302。但这是一个有争议的问题,即使您使用位置标头成功将状态设置为 401,浏览器也不会遵循重定向。

于 2012-11-20T23:40:56.663 回答
4

浏览器不会让你这样做;您不能使用 401 重定向。

于 2012-11-20T23:41:05.713 回答
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一旦您发送a,它将为您修复为302 Location(因为默认情况下状态为200,因此需要更新。PHP不检查它是否已经已更新为其他内容)。

于 2012-11-21T00:18:17.120 回答
0

正如其他人指出的那样,没有 401 重定向之类的东西。我迷上这个的原因是因为我需要重定向非 AJAX 用户,但AJAX 请求应该得到 401


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

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

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


如果您使用的是普通 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;
于 2012-11-21T20:12:24.743 回答