如何使用XMLHTTPRequest处理CSRF令牌?

时间:2018-02-07 09:14:40

标签: javascript xmlhttprequest csrf

我正在使用受CSRF保护的API。所以我需要进行一次get调用来获取CSRF令牌,然后传递相同的令牌来进行POST调用。

以下是我尝试的方式,但我总是将CSRF令牌验证失败作为POST调用的响应。

var tryout = new XMLHttpRequest();
tryout.open("GET", "/api/1.0/csrf");
tryout.withCredentials = true;
tryout.setRequestHeader("x-csrf-token", "fetch");    
tryout.setRequestHeader("Accept", "application/json");
tryout.setRequestHeader("Content-Type", "application/json; charset=utf-8");
tryout.onreadystatechange = function () {
    console.log(this);
    var csrfToken = this.getResponseHeader('x-csrf-token');
    if(tryout.readyState == 4){
        console.log(csrfToken);
        tryout.open('POST', '/api/1.0/create');
        tryout.setRequestHeader('x-csrf-token', this.getResponseHeader('x-csrf-token'));            
        tryout.onreadystatechange = function () {
            console.log("call 2");
            console.log(this.responseText);
        };
        tryout.send();
    }
};
tryout.send();

我怀疑可能是POST呼叫正在启动新会话,因此CSRF对该会话无效。

请指导我如何在同一个会话中进行两次xhr呼叫?

2 个答案:

答案 0 :(得分:0)

“x-csrf-token”,“fetch”用于GET方法获取数据。然后,您将获得csrf标记值。只需复制它并在代码中添加它可能会起作用。

答案 1 :(得分:0)

我尝试使用相同的xhr对象对XMLHTTPRequest进行同步调用以进行两次调用(获取csrf标记和下一个http post调用,在标头中传递csrf标记并且它有效。下面是示例代码。

var res = null;
var tryout = new XMLHttpRequest();  
tryout.open("GET", "/odata/1.0/service.svc", false);
tryout.withCredentials = true;
tryout.setRequestHeader("x-csrf-token", "fetch");    
tryout.setRequestHeader("Accept", "application/json");
tryout.setRequestHeader("Content-Type", "application/json; charset=utf-8");
tryout.send(null);

if(tryout.readyState === 4){
  var csrfToken = tryout.getResponseHeader('x-csrf-token');   

  tryout.open('POST', '/odata/1.0/service.svc/Clients', false);
  tryout.setRequestHeader('x-csrf-token', csrfToken);       
  tryout.setRequestHeader("Content-Type", "application/json; charset=utf-8");
  tryout.setRequestHeader("Accept", "application/json");

  tryout.send(JSON.stringify(obj));

  if(tryout.readyState === 4){
      res = JSON.parse(this.responseText);
  }
}