Django:在C#.net中进行PUT时,CSRF令牌丢失或不正确

时间:2018-09-05 18:59:38

标签: c# django rest django-rest-framework csrf

我正在为c#中的某个应用程序构建一个插件,该插件必须与Django rest接口通信。 如您所知,Django使用CSRF令牌来提高安全性。

对Django进行POST / PUT调用时遇到问题。该呼叫将始终返回“ CSRF失败:CSRF令牌丢失或不正确。”。 我在浏览器中测试了该调用(Web界面也可以编辑数据,并且将调用相同的PUT请求),令我惊讶的是,X-CSRFToken标头中使用了一个与cookie中存储的值不同的csrf令牌值。 X-CSRFToken标头是否应该使用新生成的令牌?在此调用之后,将不再使用X-CSRFToken值(旧的csrftoken值仍用于所有后续调用...)。

也许我也阅读了有关csrf令牌的Django文档。即使我认为我了解它是如何工作的,我也不知道为什么要在POST / PUT中使用新令牌。有很多示例在我的C#插件中无法使用。

在做PUT之前我要做什么:

  • 通过请求登录页面中包含csrfmiddlewaretoken的登录页面来获取CSRF令牌。
  • 存储带有令牌作为值的cookie“ csrftoken”(不幸的是,cookie不会自动存储)
  • 使用凭据登录用户(POST)(csrfmiddlewaretoken = {token}也作为参数传递)

完成上述操作后,所有GET调用均正常运行。 当我尝试执行POST或PUT时会发生问题。 这是我的PUT代码,忽略了json和url的生成,因为这不是问题:

// The _csrftoken used here, is the one I fetch at the beginning
Client().DefaultRequestHeaders.Add("X-CSRFToken", _csrftoken);

// The content is json
var response = Client().PutAsync(url, content).GetAwaiter().GetResult();

// The returned content is: {"detail":"CSRF Failed: CSRF token missing or incorrect."}"
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

// 403 is returned
if (response.IsSuccessStatusCode) { ... }

上面的代码具有以下状态:

  • 用户已登录(会话ID cookie可用)
  • csrf令牌可通过登录获得(csrftoken cookie也可用)

我试图解决的问题:

  • 将csrfmiddlewaretoken = {token}作为参数传递
  • 存储X-CSRFToken cookie
  • 使用从Web界面中完成的PUT复制的X-CSRFToken
  • 尝试使用HttpWebRequest而不是PutAsync
  • 通过从Web界面中完成的PUT复制所有标头/参数/ cookie,从Web界面中复制PUT
  • ...

有人可以帮助我了解我在做什么错吗?

非常感谢您能给我的帮助。

1 个答案:

答案 0 :(得分:0)

所以这里的问题是我们试图在浏览网页的上下文之外使用该API,而纯粹是将其用作执行GET / POST / ..调用的API。当您使用CSRF令牌时,这将不起作用,因为当在html页面中以cookie和元数据的形式浏览时,这些令牌会一起传递。

因此,仅当在浏览上下文中使用API​​时,才能将具有CSRF令牌的api一起使用。 如果要在该上下文之外使用API​​,则需要使用其他身份验证形式,例如OAuth2。

要使此功能在没有浏览上下文的情况下有效,您必须为每个POST / PUT / DELETE获取一个html页面,以获取新的CSRF令牌,您必须将其随调用一起传递。 显然,这会带来很多开销,而这并不是您要使用API​​的方式。

我请API开发人员提供OAuth2身份验证。