Я пытаюсь реализовать защиту в одном приложении от CSRF.
В PHP это относительно просто реализовать. У меня много вопросов о том, как это сделать с Extjs.
Книги EXTJS, которые я читаю, не затрагивают эту тему, и я не могу найти конкретных указаний по этому вопросу с EXTJS в Интернете.
Некоторые вопросы:
Используя PHP, токен отправляется в EXTJS?
Нужно ли создавать скрытые поля в каждой форме, как в PHP?
Нужно ли отправлять на серверную сторону токен в Ext.Ajax.requestt? Как это сделать?
Несколько очень простой код в качестве отправной точки:
жетон класса: https://www.youtube.com/watch?v=VflbINBabc4
<?php
class Token {
public static function generate() {
$_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32));
}
public static function check($token) {
if(isset($_SESSION['token']) && $token === $_SESSION['token']){
unset($_SESSION['token']);
return true;
}
return false;
}
}
?>
запрос
<?php
require('conect.php');
require_once('token.php');
$action = $_REQUEST['action'];
switch($action){
case "create":{
$records = $_POST['records'];
$data = json_decode(stripslashes($records));
if(isset($_POST['cars'], $_POST['token'])){
$cars = $data->{'cars'};
if(Token::check($_POST['token'])){
$sqlQuery = "INSERT INTO the_cars (cars) VALUES (?)";
if($statement = $con->prepare($sqlQuery)){
$statement->bind_param("s", $cars);
$statement->execute();
$success= true;
}else{
$erro = $con->error;
$success = false;
}
}else{
//error
}
echo json_encode(array(
"success" => $sucess,
'errors'=> $erro
));
$statement->close();
$conexao->close();
break;
}
}
?>
Буду признателен за помощь в том, чтобы детально понять, как реализовать этот тип защиты, используя приведенный выше код в качестве примера.
Заранее спасибо.
Несколько полезных постов:
Предотвращение CSRF для вызова AJAX из extjs в действие Struts
Как реализовать CSRFGuard в ExtJs AjaxRequest?
Синхронизация ExtJS Store с включенным Spring Security
http://blog.gugl.org/archives/category/extjs
РЕДАКТИРОВАНИЕ
Мне нравится одна возможность — отправлять токен на каждый запрос Ajax: https://www.sencha.com/forum/showthread.php?134125
Мейб в Aplication.js. файл
init: function () {
Ext.require(["Ext.util.Cookies", "Ext.Ajax"], function(){
// Add csrf token to every ajax request
var token = Ext.util.Cookies.get('csrftoken');
if(!token){
Ext.Error.raise("Missing csrftoken cookie");
} else {
Ext.Ajax.defaultHeaders = Ext.apply(Ext.Ajax.defaultHeaders || {}, {
'X-CSRFToken': token
});
}
});
}
ИЛИ от Создание приложений с помощью EXT JS видео публикуется PACKT, но с узлом на стороне сервера
var csrfToken = Ext.query('meta[name=csrf-token]')[0].getAttribute('content');
Ext.Ajax.defaultHeaders = ('X-CSRF-Token': csrfToken);
Ext.Ajax.extraParams = {'csrf': csrfToken};
У меня все еще есть сомнения относительно того, как правильно связать сторону сервера (сгенерировать токен и выполнить соответствующую проверку) со стороной клиента.
РЕДАКТИРОВАНИЕ
За последние несколько дней я сделал несколько попыток запустить CSRFProtector с php и EXTJS.
Из проведенного анализа я смог проверить следующее с помощью Chrome Dev Tools:
Если только в начале файла указатель я добавляю (а не в другие файлы php):
include_once __DIR__ .'csrfp/libs/csrf/csrfprotector.php';
csrfProtector::init()
Я пользуюсь Chrome Dev Tools:
Файл csrfprotector.js загружен
В загруженных файлах php у меня есть »Метод: POST, Status 200, Тип xhr, Инициатор csrfprotector.js: 259
Я вижу, что данные (в формате JSON) и токен отправляются и запрашивают заголовки как cookie с тем же токеном
Кроме того, в файле index.php, как и ожидалось, создается следующее:
(...)
<script type="text/javascript"src="http://my_path/csrfp/js/csrfprotector.js"></script>
<script type="text/javascript">
window.onload = function() {
csrfprotector_init();
};
</script>
</body>
</html>
Ошибка не возвращается
Когда я добавляю в начале php-файл (содержащий запрос, который получит данные запроса, например, для создания записи), include_one и csrfProtector :: init () запрос выполняется, успех ложен, и я получаю код состояния 403 и сообщение 403 Доступ запрещен CSRFProtector!
Если я добавлю эхо ‘Test 1’, перед csrfProtector :: init (); и эхо «Test 2» после, только первое эхо работает. Так что это не проблема в моем php-коде, но в проверке csrfprotector.
В Dev Tools вы видите, что ошибка 403 вызывается при упоминании следующей строки скрипта: csrfprotector: 259.
строка 259 этого файла: вернуть this.old_send (data);
Я собираюсь исследовать возможную несовместимость csrfprotector с JSON.
Если бы мы смогли запустить CSRFProtector с PHP и EXTJS (с JSON), это было бы решение, которое могло бы иметь значение для многих, поскольку его очень легко реализовать.
Пример формата данных, полученных на стороне сервера:
Array
(
[action] => create
[_dc] => 1505398990654
[data] => {"id_cars":"id_1","cars":"test"},
)
Учитывая, что вы используете PHP, мое основное предложение — взглянуть и использовать какое-то существующее решение, такое как CSRF-протектор которая специально разработана для использования с PHP и должна работать с любой клиентской средой, включая ExtJS. Вероятно, это намного лучше и безопаснее, чем все, что вы можете сделать сами.
ПРИМЕЧАНИЕ: вики проекта теперь содержит две разные страницы со ссылками на скачивание — этот содержит ссылки на устаревшая версия а также этот ссылки на новейшая версия. Обязательно загрузите текущую версию или клон репо!
Я знаю, что ваш вопрос нацелен на решение ExtJS, но оно слишком широкое и содержит некоторые важные детали, необходимые для хорошего ответа. Далее следуют некоторые вещи, которые вам нужно решить, прежде чем вы сможете начать думать о том, «как сделать это в коде» …
Прежде чем я углублюсь в детали, я настоятельно рекомендую проверить следующую страницу для общих соображений при разработке защиты CSRF: Шпаргалка по профилактике межсайтовых запросов (CSRF)
Есть и другие способы защиты от CSRF. Для простоты я буду обсуждать только способ «Токены синхронизатора (CSRF)», описанный на странице, упомянутой выше.
Защита от CSFR с использованием токенов Synchronizer (CSRF) всегда работает следующим образом:
APP.MyApp
учебный класс. Этот запрос также должен сгенерировать токен CSRF, сохранить его в сеансе (для последующей проверки), а также как-то включить его в сгенерированный ответТеперь есть еще несколько способов отправки сгенерированных токенов CSRF с сервера на клиент — мета, cookie, скрытое поле (все это упоминается в вашем вопросе). Правильный способ сделать это действительно зависит от вашего приложения и желаемого уровня защиты.
Основные соображения:
Как описано в пункте 1. выше, токен генерируется только при запросе страницы, инициирующей защищенное действие.
Это хорошо для многостраничного приложения, потому что перед тем, как защищенное действие может быть вызвано, должна быть сгенерирована страница, содержащая форму \ ссылку (и токен). Это означает, что очень легко использовать токены для каждого запроса, и вы можете отправить токен в скрытом поле мета или формы.
В приложении SPA на другой стороне, где исходная страница создается только один раз, и защищенное действие может быть выполнено несколько раз без полного обновления страницы, ваши возможности ограничены. Либо вы должны использовать токен для каждой сессии (см. Ниже), переданный через meta \ header, либо вы должны использовать более сложный механизм для получения нового токена с помощью AJAX каждый раз, прежде чем вызывать защищенное действие. В этом случае лучше использовать cookie, как описано в приведенной выше ссылке в главе «Double Submit Cookie».
Сначала вам нужно решить, будет ли ваш токен для каждого сеанса или для каждого запроса. Токены для каждого запроса генерируются для каждого запроса страницы, инициирующей защищенное действие, и удаляются после его использования (т. Е. Защищенное действие выполняется после успешной проверки токена). Может храниться в поле meta \ header \ hidden. По определению, они также не могут использоваться в приложениях SPA.
Существуют также проблемы с удобством использования, такие как кнопка «назад», приводящая к ложному срабатыванию события безопасности на сервере, если предыдущая страница защищена.
Персональные токены генерируются только один раз.
Это может привести к снижению безопасности, поскольку позволяет повторять атаки, но если ваш сайт безопасен XSS (что и должно быть), это нормально. Токены сеанса проще использовать в приложениях SPA. Может быть передано через мета \ скрытое поле.
Похоже, что текущая версия CSRF-Protector (v0.2.1) не работает с запросами POST, содержащими полезную нагрузку JSON (application/json
) — увидеть Эта проблема в трекере ошибок проекта. Чтобы обойти это, убедитесь, что вы всегда POST с Content-type: application/x-www-form-urlencoded
,
Для регулярных запросов с использованием Ext.Ajax.request
сделать это с помощью params
конфиг вместо jsonData
(играть на скрипке)
Ext.Ajax.request({
url: 'https://jsonplaceholder.typicode.com/posts/',
method: 'POST',
params: {
"userId": 1,
"id": 1,
"title": "sunt",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et"}
})
Для магазинов убедитесь, что вы настроили писатель с encode: true
(увидеть документы) как это (играть на скрипке):
var store = new Ext.data.Store({
model: 'MyApp.model.Post',
storeId: 'postsStore',
autoLoad: true,
autoSync: true,
loading: true,
proxy: {
type: 'rest',
actionMethods: {
create: 'POST',
read: 'GET',
update: 'PUT',
destroy: 'DELETE'
},
api: {
create: 'https://jsonplaceholder.typicode.com/posts',
read: 'https://jsonplaceholder.typicode.com/posts',
update: 'https://jsonplaceholder.typicode.com/posts',
destroy: 'https://jsonplaceholder.typicode.com/posts'
},
reader: {
type: 'json',
rootProperty: 'data',
totalProperty: 'total',
successProperty: 'success'
},
writer: {
type: 'json',
writeAllFields: true,
encode: true,
rootProperty: 'data'
}
}
});
Других решений пока нет …