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 中,我能够通过<?php echo csrf_token() ?>
获得该令牌,因此我在前端使用该值创建一个标头 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() 没有得到指定的标头?的主要内容,如果未能解决你的问题,请参考以下文章