2013-09-03 4 views
5

Я пытаюсь получить значение заголовка с:laravel 4: почему Request :: header() не получает указанный заголовок?

Request::header('csrf_token')

хотя мой поджигатель говорит в заголовках, которые я имею csrf_token набор для baMDpF0yrfRerkdihFack1Sa9cchUk8qBzm0hK0C. На самом деле, я могу получить, что csrf_token вместо с машинным кодом PHP:

getallheaders()['csrf_token']

Теперь вопрос я делаю свою XSRF защиты от права? или, может быть, есть недостаток в том, что PHP код, который я сделал, что я действительно должен использовать Buggy Laravel 4 функция

Request::header('csrf_token')

, который не возвращает ничего, кроме пустой. И я что-то пропустил. возможно, в моих конфигурациях Laravel 4 и т. д.?

P.S: Я использую AngularJS, но, возможно, не имеет значения, какие клиенты я использую. У меня есть эта связь, как мой гид: How to send csrf_token() inside AngularJS form using Laravel API?

+0

Позвольте мне задать небольшой вопрос: почему вы ожидаете, что 'Request :: header ('csrf_token')' возвращает это значение заголовка в первую очередь? Просто из-за имени класса-метода? Вы изучили источник этого метода, что он на самом деле делает? – hakre

+0

@hakre: спасибо за этот комментарий и идею. Исходный код, который вы говорите? хм, я не нахожу это легко и интуитивно понятно. Итак, какая должна быть подходящая функция для использования? if not Request :: header(); например, как Content-type был извлечен в документации laravel four; Request :: заголовок ('Content-Type'); – TyrHunter

+0

Я просто хотел узнать, почему вы выбрали этот код. Как показывает ваш комментарий, отсутствует какое-то минимальное понимание, которое не соответствует критериям для этого веб-сайта Q & A, поскольку вы даже не ожидаете, что этот код будет работать и воспроизвести проблему. Я предлагаю вам спросить на форумах Laravel 4. – hakre

ответ

1

Request::header() действительно используется для retrieval of headers, но проверить, где маркер создается .. маркер CSRF должен быть placed into the session by Laravel, а затем она может быть доступна через метод Session::token() ,

Если вы посмотрите на HTML, сгенерированный с помощью вызовов класса Form::, вы увидите скрытый элемент с именем _token, который затем следует сравнить с токеном в сеансе. Вы можете получить доступ к этому, используя Input::get('_token'), как и любые другие входящие переменные GET или POST.

... Тем не менее, все это не должно быть действительно необходимо, так как это может быть легко управляется с помощью заранее определенного CSRF фильтра в filters.php, просто add that filter to the desired route or route group, и вы будете защищены, без необходимости вдаваться в подробности из этого.

+0

Здравствуйте. Я не могу использовать класс формы :: laravel, так как мои формы генерируются Angularjs как мой интерфейс. Но это не проблема. В моем SPA я смог получить этот токен с помощью '', Поэтому я использовал это значение в своем интерфейсе, чтобы создать заголовок csrf_token, который затем будет считываться и сопоставляться с Session :: token() (который отлично работает) laravel4, хотя я могу получить это путем getallheaders() ['csrf_token']; Мне просто интересно, почему Request :: header ('csrf_token') возвращает пустые – TyrHunter

+0

ах, извинения, пропустил эту часть! Я думаю, Хакре был прав, лучше всего занять на форумах laravel! :) – msturdy

0

проблема связана с объектом Symfony Request, который расширен в рамках Laravel. Смотрите эту GitHub нити

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

Решения в вашем случае было бы установить имя заголовка для HTTP_CSRF_TOKEN или HTTP_X_CSRF_TOKEN, если вам нравится префиксы X для пользовательских заголовков HTTP.

2

Я думаю, проблема в том, что в следующем ответе на How to send csrf_token() inside AngularJS form using Laravel, который вы использовали, csrf_token не отправляется в заголовке вашего XMLHttpRequest, а в форме он сам.

Вам необходимо затем отфильтровать его в своем laravel backend как обычное поле ввода. Ниже рабочий пример:

Route::filter('csrf_json', function() 
{ 
    if (Session::token() != Input::get('csrf_token')) 
    { 
     throw new Illuminate\Session\TokenMismatchException; 
    } 
}); 

UPDATE

Если вы хотите использовать заголовки в Угловом, вы предпочли бы написать что-то вроде:

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

Для того, чтобы aplly новых заголовок в XMLHttpRequests.Тогда легко catchable даже с сырой PHP, такие как:

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

Я решила эту проблему путем удаления подчеркивания «_» в csrf_token так будет crsftoken вместо этого.

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

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

По-видимому, у Laravel проблемы с именами заголовков, у которых есть символы подчеркивания? – astroanu

+0

это решило мою проблему. я бы никогда не догадался, что это проблема. –

+0

Это решило мою проблему! Большое спасибо. –

1

Проблема

Laravel удаляет заголовки с подчеркивания в имени при их извлечении с помощью метода Request::header(). Кроме того, все имена заголовков преобразуются в нижний регистр в методе Request::header().

Короткое решение

На веб-интерфейсе, заменить все символы подчеркивания в именах заголовков с черточками. csrf_token становится csrf-token

Long Решение

Добавить маркер Laravel CSRF как угловые постоянная на главной странице/макете.

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

Добавить маркер в качестве заголовка по умолчанию для всех ваших запросов в угловом.

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

Пусть ваш csrf фильтр Laravel проверить на матч в заголовках, а не вход.

/** 
* 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.", 
      ), 
     )); 
    } 
}