2013-11-25 2 views
3

У меня возникла следующая проблема с токенами XSRF.Настройка сеанса PHP на индексной странице для проверки XSRF

Клиент: AngularJS Сервер: PHP

Когда index.php хит, PHP генерирует XSRF маркер и сохраняет его в сессии. Файл cookie устанавливается с одинаковым значением.

AngularJS считывает файл cookie и сохраняет его.

При последующих POSTS токен XSRF отправляется как заголовок, и идея заключается в сравнении сохраненного токена сеанса с отправленным заголовком.

Все кажется прекрасным, никаких проблем.

НО: проблема в том, что PHP не может прочитать сеанс, зарегистрированный в index.php, потому что технически не было перезагрузок страниц! Если я удалю F5 и перезагрузим все, сеанс будет хорошо прочитан.

Как установить токен сеанса XSRF на index.php и получить его для последующих запросов ajax от клиента? Я вытягиваю волосы на этом ... ценю обратную связь.

UPDATE

После изменения имени идентификатора сеанса, все вдруг сработало!

В index.php:

// Create token and set session 
session_start(); 
$token = hash('sha256', uniqid(mt_rand(), true)); 
$_SESSION['XSRF']=$token; 

Позже, также в index.php:

/* Give token to Angular client */ 
<script> 
angular.module("app").constant("CSRF_TOKEN", '<?=$_SESSION['XSRF'];?>'); 
</script> 

Обратите внимание, что я не использую печенье, вместо этого я установить константу, которая затем сделал доступны для метода .run в угловом:

в Угловом:

angular.module('app').run(['CSRF_TOKEN','$http',function(CSRF_TOKEN,$http) { 

    $http.defaults.headers.common['CSRF_TOKEN'] = CSRF_TOKEN; 

Все запросы на сервер направляются в один общий файл php. Проверяет файл, если заголовок установлен, и сравнивает два маркера:

// Only POST requests are checked (I don't use PUT/DELETE) 
if($_SERVER['REQUEST_METHOD']=="POST"){ 
    session_start(); 
    $headerToken = $_SERVER['HTTP_CSRF_TOKEN']; 
    $sessionToken = $_SESSION['XSRF']; 
    if($headerToken!=$sessionToken){ 
     header('HTTP/1.0 401 Unauthorized'); 
     exit; 
    } 
} 
+0

Вы отправляете на index.php в свои $ http-вызовы или на другую страницу php на своем сервере? Если я понимаю вашу проблему, это то, что php-файл получает пустой сеанс? –

+0

Если я правильно понимаю ...Вы можете сгенерировать переменную токена XSRF с помощью PHP и поместить в JS-код, если хотите, чтобы он был доступен для аякс-запросов ... Возможно, какой-то пример вашего кода поможет? –

+0

Нет причин для этого не работать. По первому запросу вы создаете сеанс и токен и возвращаете куки-файл сеанса с первым ответом. Сессия существует сейчас, все последующие запросы имеют активный сеанс. Нам понадобится дополнительная информация, чтобы помочь вам здесь. – deceze

ответ

4

Это то, что я делаю в моем PHP/AngularJS проектов:

index.php

session_start(); 
if (!isset($_SESSION['XSRF-TOKEN'])) { 
    $uniqueValues = md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']); //add more/less/any "unique" values, see comments 
    $_SESSION['XSRF-TOKEN'] = sha1(uniqid(microtime() . $uniqueValues, true)); 
    setcookie('XSRF-TOKEN', $_SESSION['XSRF-TOKEN']); 
} 

любой скрипт, вызываемый AngularJS $ http:

(AngluarJS использует значение cookie XSRF-TOKEN и отправляет его в каждом запросе в качестве настраиваемого заголовка X-XSRF-TOKEN, поэтому нам нужно сравнить это значение со значением, хранящимся в сессии.)

function verifyXSRF() { 

    /* 
    $headers = apache_request_headers(); 
    $headerToken = ""; 
    foreach ($headers as $header => $value) { 
     if ($header == "X-XSRF-TOKEN") { 
      $headerToken = $value; 
      break;   
     } 
    } 
    */ 

    //more efficient, see comments 
    $headerToken = $_SERVER['HTTP_X_XSRF_TOKEN']; 

    if ($headerToken != $_SESSION['XSRF-TOKEN']) return false; 
    return true; 
} 

session_start(); 
if (!verifyXSRF()) die("XSRF error"); 

Обратная связь приветствую, поскольку я точно не знаю, достаточно ли защиты XSRF.

+0

Привет, спасибо за ваш ответ. Это также в основном, как я это делаю. Кстати, более простой способ проверить наличие HTTP-заголовка - просто использовать $ headerToken = $ _SERVER ['HTTP_XSRF_TOKEN'], нет необходимости перебирать все заголовки. Также помните, что Angular отправляет только заголовок на запросы POST, PUT и DELETE, а не GET – Spock

+0

. Я предлагаю поставить нечто более уникальное, чем microtime() как «случайный» генератор, например, поместив идентификатор пользователя, IP-адрес, доступ к которому страница и т. д., увеличит сложность и затруднит угадать XSRF-TOKEN. Я также предлагаю минимизировать экспозицию файла cookie, используя httponly (если возможно) и параметры пути – nrathaus

+0

отлично, спасибо за ввод, я улучшу код. – efdev1234

Смежные вопросы