laravel 4:为啥 Request::header() 没有得到指定的标头?

Posted

技术标签:

【中文标题】laravel 4:为啥 Request::header() 没有得到指定的标头?【英文标题】:laravel 4: why is Request::header() not getting the specified header?laravel 4:为什么 Request::header() 没有得到指定的标头? 【发布时间】:2013-09-06 06:39:10 【问题描述】:

我正在尝试获取标题值:

Request::header('csrf_token')

不过,我的萤火虫在标题中说我将 csrf_token 设置为 baMDpF0yrfRerkdihFack1Sa9cchUk8qBzm0hK0C。事实上,我可以使用原生 php 代码来获取 csrf_token

getallheaders()['csrf_token']

现在的问题是我的 XSRF 保护正确吗?或者我做的那个 php 代码有一个缺陷,我真的必须使用有问题的 laravel 4 函数

Request::header('csrf_token')

它只返回空白。我只是错过了一些东西。也许在我的 Laravel 4 配置等中?

P.S:我正在使用 AngularJS,但也许我使用什么客户端并不重要。我有这个链接作为我的指南:How to send csrf_token() inside AngularJS form using Laravel API?

【问题讨论】:

请允许我回答一个小问题:为什么您希望Request::header('csrf_token') 首先返回该标头值?仅仅因为类方法的名称?您是否查看过该方法的来源,它实际上做了什么? @hakre:感谢您的评论和想法。你说的源代码?嗯,我觉得这不容易和直观。那么必须使用什么合适的功能呢?如果不是 Request::header();就像在 laravelfour 的文档中如何检索 Content-type 一样;请求::header('Content-Type'); 我只是想了解您选择该代码的原因。正如您的评论所示,似乎缺少某种最低限度的理解,这是此问答网站的题外话标准,因为您甚至不希望有问题的代码能够工作并重现问题。我建议您改为在 Laravel 4 论坛中询问。 有关您编写的代码问题的问题必须在问题本身中描述具体问题 - 并且包含重现问题的有效代码。请参阅SSCCE.org 获取指导。 好吧,那我看看。谢谢 【参考方案1】:

我通过删除 csrf_token 中的下划线“_”解决了这个问题,所以它会改为 crsftoken。

Request::header('csrf_token'); // Not working

Request::header('csrftoken'); // Working!

【讨论】:

显然 Laravel 的标题名称有下划线的问题? 这也解决了我的问题。我永远不会想到这是问题所在。【参考方案2】:

我认为问题在于,在您使用的How to send csrf_token() inside AngularJS form using Laravel 的以下答案中,csrf_token 不是在您的 XMLHttpRequest 的标头中发送,而是以它自己的形式发送。

然后您需要在 laravel 后端将其过滤为常规输入字段。请参阅下面的工作示例:

Route::filter('csrf_json', function()

    if (Session::token() != Input::get('csrf_token'))
    
        throw new Illuminate\Session\TokenMismatchException;
    
);

更新

如果你想在 Angular 中使用标题,你宁愿写这样的东西:

$httpProvider.defaults.headers.common['Authorization'] = TOKEN;

为了向您的 XMLHttpRequests 应用一个新的标头。然后即使使用原始 php 也很容易捕获,例如:

$aHeaders = getallheaders();
if (Session::token() != $aHeaders['authorization']) etc.

【讨论】:

【参考方案3】:

问题

在使用 Request::header() 方法检索标题时,Laravel 正在删除名称中带有下划线的标题。此外,Request::header() 方法中的所有标头名称都转换为小写。

短解决方案

在前端,将标题名称中的所有下划线替换为破折号。 csrf_token 变为 csrf-token

长期解决方案

在主页/布局中添加 Laravel CSRF 令牌作为 Angular 常量。

<script>
    angular.module("myApp").constant("CSRF_TOKEN", "<?php echo csrf_token(); ?>"); 
</script>

将令牌添加为 Angular 中所有请求的默认标头。

angular.module("myApp").run(function($http, CSRF_TOKEN)
    $http.defaults.headers.common["csrf-token"] = CSRF_TOKEN;
)

让你在 Laravel 中的 csrf 过滤器检查标题中的匹配项而不是输入项。

/**
 * Check that our session token matches the CSRF request header token.
 *
 * @return json
 */
Route::filter("csrf", function() 
    if (Session::token() !== Request::header("csrf-token")) 
        return Response::json(array(
            "error" => array(
                "code"    => "403",
                "message" => "Ah ah ah, you didn't say the magic word.",
            ),
        ));
    

【讨论】:

【参考方案4】:

Request::header()确实是用于retrieval of headers的,但是要检查token是在哪里设置的。CSRF token应该是placed into the session by Laravel,然后就可以通过Session::token()访问了 方法。

如果您查看通过调用 Form:: 类生成的 html,您会看到一个名为 _token 的隐藏元素,然后应将其与会话中的令牌进行比较。您可以使用 Input::get('_token') 访问它,就像使用任何其他传入的 GET 或 POST 变量一样。

...但是,所有这些都不是必需的,因为它可以通过filters.php 中的预定义CSRF 过滤器轻松管理,只需add that filter to the desired route or route group,您将受到保护,无需深入了解它的细节。

【讨论】:

你好。我不能使用 laravel 的 Form:: 类,因为我的表单是由 Angularjs 作为我的前端生成的。但这不是问题。在我的 SPA 中,我能够通过&lt;?php echo csrf_token() ?&gt; 获得该令牌,因此我在前端使用该值创建一个标头 csrf_token,然后 laravel4 将读取并匹配到 Session::token() (这很好),不过我可以通过 getallheaders()['csrf_token'];我只是想知道为什么 Request::header('csrf_token') 返回空 啊,抱歉,错过了那部分!我认为 Hakre 是对的,最好加入 laravel 论坛! :)【参考方案5】:

问题在于在 Laravel 框架中扩展的 Symfony Request 对象。看到这个github线程

https://github.com/laravel/framework/issues/1655#issuecomment-20595277

如果您喜欢在自定义 http 标头前加上 X 前缀,则解决方案是将标头名称设置为 HTTP_CSRF_TOKEN 或 HTTP_X_CSRF_TOKEN。

【讨论】:

以上是关于laravel 4:为啥 Request::header() 没有得到指定的标头?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Laravel 4 CSRF 令牌不起作用?

laravel 5.4 指定的key太长,为啥数字191

为啥我的 Laravel 模块中出现“找不到类”错误?

为啥我的 Facades 在更新到 Laravel 7.3 后停止工作?

laravel 设置好了路由为啥找不到控制器

为啥 laravel 中的刀片文件不显示?