当 POST 是唯一方法时,如何使用 jQuery 从标头中检索 csrf 令牌?

Posted

技术标签:

【中文标题】当 POST 是唯一方法时,如何使用 jQuery 从标头中检索 csrf 令牌?【英文标题】:How to retrive csrf token from header with jQuery when POST is only method? 【发布时间】:2018-01-26 07:32:44 【问题描述】:

我正在用 Spring 编写 Rest Api,并将 jQuery 用于前面使用此 api 的应用程序。会话存储在 cookie 中,因此我需要使用令牌进行 CSRF 保护。令牌在请求/响应标头中发送并存储在页面上的元标记中。 这不是完整的 SPA,因此在身份验证和注册时,我发送单独的 html 页面:index.html(用于经过身份验证的用户)、login.html(登录页面)、register.html(注册页面)。这是问题所在,我不知道如何在注册和登录时检索 csrf 令牌,因为第一个也是唯一的请求始终是 POST 但不知何故我需要先在页面上设置 csrf 令牌。我检索的静态页面只是通过调用静态资源:window.location = '/register.html';例如。我尝试为“/token”端点设置获取请求,该端点仅返回带有状态的 ResponseEntity 并从标头中获取令牌,但随后在 javascript 中显示错误 jqXHR.getResponseHeader('X-CSRF-TOKEN') 不是函数... 。 诡异的。在这种情况下,如何使用 jquery 编写从标头中检索令牌的方法?

例如,这里是我的 register.js 文件以及我如何处理获取和附加令牌。

In login page i have button whch redirects on registration page:

 $('#registerBtn').on('click', function () 
    window.location = '/register.html';
);
--------------------------------
And registration page is: 

    $(document).ready(function () 
    setCsrfToken();
    $('#submit').on('click', function () 
        return $.ajax(
            url: '/registration',
            type: 'POST',
            beforeSend: function (request) 
                setHeaderWithCsrfToken(request);
            ,
            data: $('#registrationForm').serialize(),
            timeout: 3000
        ).then(function (data, textStatus, jqXHR) 
            console.log(jqXHR.status);
        , function (jqXHR) 
            if (jqXHR === 422) 
                // $('#registrationForm').append(jqXHR);
                alert(jqXHR.status);
             else 
                alert(jqXHR.status);
            
        );
    );
);

// simple get method to retrieve response header with token
function setCsrfToken()  // TODO: how to make it reusable?
    return $.ajax(
        url: '/token',
        type: 'GET',
        timeout: 3000
    ).always(function (jqXHR) 
        getCsrfToken(jqXHR);
    );


function getCsrfToken(jqXHR) 
    $('meta[name="X-CSRF-TOKEN"]').attr('content', 
jqXHR.getResponseHeader('X-CSRF-TOKEN'));
    $('meta[name="X-CSRF-HEADER"]').attr('content', 
jqXHR.getResponseHeader('X-CSRF-HEADER'));


function setHeaderWithCsrfToken(request) 
    var token = $('meta[name="X-CSRF-TOKEN"]').attr('content');
    var header = $('meta[name="X-CSRF-HEADER"]').attr('content');
    request.setRequestHeader(header, token);

【问题讨论】:

【参考方案1】:

我认为您在 AJAX 回调函数中使用了错误的参数。试试这个:

$.ajax(
    url: '/token',
    type: 'GET',
    timeout: 3000
).done(function (data, textStatus, jqXHR) 
    getCsrfToken(jqXHR);
);

【讨论】:

.done() 在我的情况下无法由 jQuery 解决,我不知道。但是我使用 .then() 代替 .always() 并工作

以上是关于当 POST 是唯一方法时,如何使用 jQuery 从标头中检索 csrf 令牌?的主要内容,如果未能解决你的问题,请参考以下文章

为啥当我得到我的数据时似乎未定义/为空?我正在使用 jQuery.post() 从 JS 向 PHP 发送数据

jQuery .ajax() POST 请求抛出 405(不允许的方法)但 GET 不会

jquery的post异步请求

当没有找到与 Rails 的 JQuery 自动完成匹配时如何显示响应

如何使用 ajax Post 方法在没有 jQuery 的情况下提交用户输入

如何使用 javascript/jquery/AJAX 调用 Django REST API?