Slim PHP v3 CSRF с AJAX и API выборки

я настроил нормальный CSRF и т. д. и работал бы хорошо, но потом, когда я пойду и использую ajax, используя API-интерфейс whatwg-fetch (https://github.com/github/fetch)

Теперь все кажется в порядке, и все работает хорошо, что у меня есть. НО! Затем я добавляю настройки CSRF, как показано ниже, и все время происходит сбой:

Итак, я использовал нормальный, но он терпит неудачу, и в заголовке я получаю сообщение: Failed CSRF check!

        $app->add(new \Slim\Csrf\Guard);

Но я хотел добавить собственное сообщение и т. Д., Поэтому добавил следующее, но все равно оно не проходит.

      $container['csrf'] = function ($c) {
$guard = new \Slim\Csrf\Guard;
$guard->setFailureCallable(function ($request, $response, $next) {
$request = $request->withAttribute("csrf_status", false);
return $next($request, $response);
});
return $guard;
};

$app->add($container->get('csrf'));

Затем в моем классе я проверяю это:

      if (false === $req->getAttribute('csrf_status')) {...}else{//all ok}

Но что бы ни случилось, оно всегда терпит неудачу.

в моем JS я добавляю детали токена к запросу, как:

    fetch('/post/url',{
method: 'POST',
headers: {
'X-CSRF-Token': {
'csrf_name':csrf_name,
'csrf_value':csrf_value
}
},
body: new FormData(theForm)

Я посмотрел в опубликованных данных и т. д., и данные формы представлены в том числе значения CSRF и т. д. Так что данные CSRF требуется отправлять через форму, а также заголовок?

Итак, как мне настроить Ajax для работы с Slim CSRF, чего мне не хватает?

заранее спасибо

0

Решение

Я также не смог достать, чтобы положить токены в тело. Я решил расширить класс, чтобы я мог изменить метод __invoke. Я добавил некоторый код, чтобы извлечь csrf из заголовков.

в ваших зависимостях теперь используйте этот класс.

  $c['csrf'] = function ($c) {
return new \Foo\CSRF\Guard;
};

Расширенный класс.

<?php
namespace MYOWN\CSRF;

use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;

/**
* CSRF protection middleware.
*/
class Guard extends \Slim\Csrf\Guard
{
public function __construct(
$prefix = 'csrf',
&$storage = null,
callable $failureCallable = null,
$storageLimit = 200,
$strength = 16,
$persistentTokenMode = false
) {
parent::__construct(
$prefix,
$storage,
$failureCallable,
$storageLimit,
$strength,
$persistentTokenMode);
}

public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
{

$this->validateStorage();

// Validate POST, PUT, DELETE, PATCH requests
if (in_array($request->getMethod(), ['POST', 'PUT', 'DELETE', 'PATCH'])) {
$body = $request->getParsedBody();
$body = $body ? (array)$body : [];
$name = isset($body[$this->prefix . '_name']) ? $body[$this->prefix . '_name'] : false;
$value = isset($body[$this->prefix . '_value']) ? $body[$this->prefix . '_value'] : false;

if (!empty($csrfTokens = $request->getHeader('x-csrf-token'))) {
$csrfTokens = json_decode($csrfTokens[0], true);
$name = isset($csrfTokens[$this->prefix . '_name']) ? $csrfTokens[$this->prefix . '_name'] : false;
$value = isset($csrfTokens[$this->prefix . '_value']) ? $csrfTokens[$this->prefix . '_value'] : false;
}

if (!$name || !$value || !$this->validateToken($name, $value)) {
// Need to regenerate a new token, as the validateToken removed the current one.
$request = $this->generateNewToken($request);

$failureCallable = $this->getFailureCallable();
return $failureCallable($request, $response, $next);
}
}

// Generate new CSRF token if persistentTokenMode is false, or if a valid keyPair has not yet been stored
if (!$this->persistentTokenMode || !$this->loadLastKeyPair()) {
$request = $this->generateNewToken($request);
}

// Enforce the storage limit
$this->enforceStorageLimit();

return $next($request, $response);
}}
1

Другие решения

хорошо после нескольких попыток за последний день и сужая его до fetch api Я решил вернуться к доверенным методам jQuery aJax, и это, похоже, сработало.

Кажется следующее body и new FormData() не было подобрано:

fetch('/post/url',{
method: 'POST',
body: new FormData(theForm)

Так что выключил это для

     $.ajax({
url : '/url/to/post',
type: "POST",
data: {key:value, kay:value}

И все работало хорошо.

Следующая проблема, которую следует рассмотреть, — это обновление ключей при первом вызове ajax, что предотвращает повторные вызовы, если страница не обновляется, но это на другой день.

0

Я еще раз попробовал это после прочтения одного из блогов одного из создателей. Так что вы можете игнорировать мой предыдущий ответ.

Отправка csrf в теле с этими заголовками проходит проверку csrf.

const data = {
'csrf_name': csrf_name,
'csrf_value': csrf_value,
};

fetch(apiUrl, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json, application/x-www-form-urlencoded; charset=utf-8',
},
}).then((response) => {
if (response.ok) {
return response.json();
}
return null;
}).then((json) => {
console.log(json);
}).catch(() => {
});
0

Что в итоге помогло мне добиться успеха с Slim PHP и значениями CSRF при использовании fetch добавлял credentials: 'include' на запрос о получении, например:

const body = JSON.stringify({
csrf_name: csrfName.value,
csrf_value: csrfValue.value
// You can add more data here
});

fetch('/some/request', {
method: 'POST',
body: body,
credentials: 'include',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
}).then(...)
0
По вопросам рекламы [email protected]