Защита от CSRF (Сross Site Request Forgery) в Laravel

Веб программирование Защита от CSRF (Сross Site Request Forgery) в Laravel

Помечено: , ,

  • В этой теме 0 ответов, 1 участник, последнее обновление 1 год, 4 месяца назад сделано Васильев Владимир Сергеевич.
Просмотр 0 веток ответов
  • Автор
    Сообщения
    • #5308
      @admin

      CSRF — Сross Site Request Forgery «Межсайтовая подделка запроса». По-сути вид атаки на сайт, когда подделывают запрос от клиента к серверу.

      В Laravel фреймворке есть фильтры app/filters.php и для поддержики защиты от CSRF прописывают такой фильтр:

      Route::filter('csrf', function()
      {
          if(Session::getToken() != Input::get('csrf_token') &&  Session::getToken() != Input::get('_token') )
      	{
      		throw new Illuminate\Session\TokenMismatchException;
      	}
      });

      т.е. все запросы, которые в себе несут не только данные о запрашиваемой странице, но и данные от клиента* будут обязаны содержать в заголовках ключ-идентификатор. ** (можно просто по адресу обратиться за содержимым, а можно передать какую-то форму или какие-то данные на сервер, и ждать от него ответа)

      В случае отправки формы ключ отправляем так:
      <form method="post"><input name="_token" type="hidden" value="{{{ Session::getToken() }}}" /> ...</form>

      Но в ajax запросах все немного тяжелее, т.к. нам может понадобиться отправить сериализированную форму, либо просто не захотим под каждый запрос создавать js переменную с csrf token’ом. Вариант решения задачи:

      • В хедер добавляем мета-тег
        <meta name="csrf-token" id="csrf-token" content="{{{ csrf_token() }}}">
      • Немного изменим фильтр
                Route::filter('csrf', function()
                {
                    if(
                        (Request::ajax() && Session::getToken() != Request::header('X-CSRF-Token')) ||
                        (!Request::ajax() && Session::getToken() != Input::get('csrf_token') &&  Session::getToken() != Input::get('_token') )
                    )
                	{
                		throw new Illuminate\Session\TokenMismatchException;
                	}
                });
      • Не забываем отправлять в ajax-запросах нужный заголовок с ключем:
                // для Jquery.ajax:
                $.ajaxSetup({
                    headers: {
                        'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
                    }
                });
                // Если на JS 
                xmlHttp.open("POST", options.url, true);
                // ... всякие там ваши заголовки
                xmlHttp.setRequestHeader("X-CSRF-Token", $('meta[name="csrf-token"]').attr('content'));
                // и не забудем указать для Laravel, что это именно ajax Request
                xmlHttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");

      Немного о Request::ajax()

      /**
       * Determine if the request is the result of an AJAX call.
       * 
       * @return bool
       */
      public function ajax()
      {
          return $this->isXmlHttpRequest();
      }

      где isXmlHttpRequest функция из Symfony:

      public function isXmlHttpRequest()
      {
          return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
      }

Просмотр 0 веток ответов
  • Для ответа в этой теме необходимо авторизоваться.