AJAX и CSRF весной

Я отправляю токен CSRF в заголовке HTTP-запроса и в скрытом поле POST для защиты от CSRF-атак, например:

var request;
var timeout;

function insert(callback)
{
    if(!request) 
    {
        CKEDITOR.instances.txtAboutProducts.updateElement();
        var contents=$("#txtAboutProducts").val();
        var csrf_token=$("#token").val();

        if(contents==null||contents=='')
        {
            alert("Please enter the contents.");
            return;
        }

        request = $.ajax({
            headers: { 
                    'Accept': 'application/json',
                    'Content-Type': 'application/json' 
                },
            datatype:"json",
            type: "POST",
            url: "../admin_side/AboutProducts.htm",
            data: JSON.stringify({"contents":contents, "token":csrf_token}),

            beforeSend: function (xhr)
            {
                xhr.setRequestHeader('X-CSRF-Token', csrf_token); 
            },
            success: function(response)
            {
                callback(response);
            },
            complete: function()
            {
                timeout = request = null;
            },
            error: function(request, status, error)
            {
                if(status!=="timeout"&&status!=="abort") // or just if(status==="error")
                {
                    alert(status+" : "+error);
                }
                callback(request);
            }
        });
        timeout = setTimeout(function() {
            if(request) 
            {
                request.abort();
                alert("The request has been timed out.");
            }
      }, 300000); //5 minutes.
    }
}

Эта функция предназначена для вставки содержимого CMS, хранящегося в CKEditor, для вставки в базу данных с помощью вызова POST AJAX для Spring через JSON (при нажатии кнопки).

Условная проверка if(!request){...} в начале тела функции просто для предотвращения дублирования вызовов AJAX (вероятно, нетерпеливыми пользователями).

Произвольно сгенерированное значение токена сохраняется в скрытом поле, как только страница загружается и извлекается в переменной JavaScript.

var csrf_token=$("#token").val();

Затем следующий обработчик устанавливает заголовок, который должен быть отправлен вместе с запросом.

beforeSend: function (xhr)
{
    xhr.setRequestHeader('X-CSRF-Token', csrf_token); 
},

Зачем нужен заголовок? Токен, отправленный как скрытое поле, сам по себе недостаточен? Нужно ли проверять заголовок из-за старых Flash Player (просто в качестве примера)?


При таком подходе на стороне сервера я проверяю, совпадают ли значения как заголовка, так и скрытого поля (вместе с проверкой наличия этого токена в сеансе {проверка наличия токена в сеансе нигде хотя упоминалось}).

Метод в классе контроллера Spring, который вызывается вышеупомянутой функцией JavaScript, выглядит следующим образом.

@RequestMapping(value=("admin_side/AboutProducts"), method=RequestMethod.POST)
private @ResponseBody CKEditorContentsHandler insert(@RequestBody final CKEditorContentsHandler object, final HttpServletResponse response, final HttpServletRequest request)
{
    if(object!=null&&StringUtils.isNotBlank(object.getToken())&&StringUtils.isNotBlank(request.getHeader("X-CSRF-Token"))&&sessionTokenService.isTokenValid(object.getToken())&&object.getToken().equals(request.getHeader("X-CSRF-Token")))
    {
        aboutProductsService.insert(object.getContents());
        object.setMessage("Insertion done successfully.");
        object.setStatus(1);
    }
    else
    {
        object.setMessage("The authentication token cannot be verified.");
        object.setStatus(-1);
    }
    return object;
}

куда CKEditorContentsHandler первый параметр этого метода - простой Java-класс, содержащий всего несколько свойств для удовлетворения потребностей.


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

После чего требуется заголовок? Каков на самом деле рекомендуемый способ защиты от (или, по крайней мере, смягчения) атак CSRF?


Следующий ответ суммирует это хорошо.

анти-CSRF токен и Javascript

0 ответов

Другие вопросы по тегам