首页 > 解决方案 > Django:在 C# .net 中执行 PUT 时 CSRF 令牌丢失或不正确

问题描述

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

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

显然,我还阅读了有关 csrf 令牌的 Django 文档。尽管我认为我理解它是如何工作的,但我不明白为什么将新令牌用于 POST/PUT。有很多示例在我的 C# 插件中使用没有意义。

我在做 PUT 之前做什么:

完成上述操作后,所有 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) { ... }

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

我试图解决的问题:

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

非常感谢你能给我的任何帮助。

标签: c#djangorestdjango-rest-frameworkcsrf

解决方案


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

因此,只有在浏览上下文中使用 API 时,才能使用带有 CSRF 令牌的 API。如果您想在该上下文之外使用 API,则需要使用不同形式的身份验证,例如 OAuth2。

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

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


推荐阅读