Django:在 C# .net 中执行 PUT 时,CSRF 令牌丢失或不正确
Django: CSRF token missing or incorrect when doing a PUT in C# .net
我正在用 c# 为某个应用程序构建一个插件,它必须与 Django 休息界面进行通信。
如您所知,Django 使用 CSRF 令牌来提高安全性。
我在对 Django 进行 POST/PUT 调用时遇到问题。调用将始终 return "CSRF Failed: CSRF token missing or incorrect."。
我在浏览器中测试了调用(Web 界面也可以编辑数据,并将调用相同的 PUT 请求),令我惊讶的是 X-CSRFToken header 中使用了不同的 csrf 令牌值,比存储在 cookie 中的那个。 X-CSRFToken header 应该使用新生成的令牌吗? X-CSRFToken 值在此次调用后不再使用(旧的 csrftoken 值仍用于所有后续调用...)。
很明显,我还阅读了有关 csrf 令牌的 Django 文档。尽管我认为我理解它是如何工作的,但我不明白为什么要对 POST/PUT 使用新的标记。有很多示例在我的 C# 插件中没有意义。
在进行 PUT 之前我做了什么:
- 通过请求包含 csrfmiddlewaretoken 的登录页面来获取 CSRF 令牌 body。
- 以令牌作为值存储一个 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) { ... }
以上代码是在以下状态下制作的:
- 用户已登录(sessionid cookie 可用)
- csrf 令牌可通过登录获得(csrftoken cookie 也可用)
我尝试解决的问题:
- 将 csrfmiddlewaretoken={token} 作为参数传递
- 存储 X-CSRFToken cookie
- 使用我从网络界面中完成的 PUT 复制的 X-CSRFToken
- 尝试使用 HttpWebRequest 而不是 PutAsync
- 通过从在 Web 界面中完成的 PUT 复制所有 headers/parameters/cookies 从 Web 界面复制 PUT
- ...
谁能帮我理解我做错了什么?
非常感谢您能给我的任何帮助。
所以这里的问题是我们试图在浏览网页的上下文之外使用 API,并且纯粹作为 api 来执行 GET/POST/.. 调用在。当您使用 CSRF 令牌时,这不起作用,因为在 html 页面中以 cookie 和元数据的形式浏览时会传递这些令牌。
因此,仅当在浏览上下文中使用 API 时,将 api 与 CSRF 令牌一起使用才有效。
如果您想在该上下文之外使用 API,则需要使用不同形式的身份验证,例如 OAuth2。
为了在没有浏览上下文的情况下工作,您必须为每个 POST/PUT/DELETE 获取一个 html 页面以获取一个新的 CSRF 令牌,您必须将其与调用一起传递。
显然这会带来很多开销,这不是您想要使用 API.
的方式
我要求 API 开发人员提供 OAuth2 身份验证。
我正在用 c# 为某个应用程序构建一个插件,它必须与 Django 休息界面进行通信。 如您所知,Django 使用 CSRF 令牌来提高安全性。
我在对 Django 进行 POST/PUT 调用时遇到问题。调用将始终 return "CSRF Failed: CSRF token missing or incorrect."。 我在浏览器中测试了调用(Web 界面也可以编辑数据,并将调用相同的 PUT 请求),令我惊讶的是 X-CSRFToken header 中使用了不同的 csrf 令牌值,比存储在 cookie 中的那个。 X-CSRFToken header 应该使用新生成的令牌吗? X-CSRFToken 值在此次调用后不再使用(旧的 csrftoken 值仍用于所有后续调用...)。
很明显,我还阅读了有关 csrf 令牌的 Django 文档。尽管我认为我理解它是如何工作的,但我不明白为什么要对 POST/PUT 使用新的标记。有很多示例在我的 C# 插件中没有意义。
在进行 PUT 之前我做了什么:
- 通过请求包含 csrfmiddlewaretoken 的登录页面来获取 CSRF 令牌 body。
- 以令牌作为值存储一个 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) { ... }
以上代码是在以下状态下制作的:
- 用户已登录(sessionid cookie 可用)
- csrf 令牌可通过登录获得(csrftoken cookie 也可用)
我尝试解决的问题:
- 将 csrfmiddlewaretoken={token} 作为参数传递
- 存储 X-CSRFToken cookie
- 使用我从网络界面中完成的 PUT 复制的 X-CSRFToken
- 尝试使用 HttpWebRequest 而不是 PutAsync
- 通过从在 Web 界面中完成的 PUT 复制所有 headers/parameters/cookies 从 Web 界面复制 PUT
- ...
谁能帮我理解我做错了什么?
非常感谢您能给我的任何帮助。
所以这里的问题是我们试图在浏览网页的上下文之外使用 API,并且纯粹作为 api 来执行 GET/POST/.. 调用在。当您使用 CSRF 令牌时,这不起作用,因为在 html 页面中以 cookie 和元数据的形式浏览时会传递这些令牌。
因此,仅当在浏览上下文中使用 API 时,将 api 与 CSRF 令牌一起使用才有效。 如果您想在该上下文之外使用 API,则需要使用不同形式的身份验证,例如 OAuth2。
为了在没有浏览上下文的情况下工作,您必须为每个 POST/PUT/DELETE 获取一个 html 页面以获取一个新的 CSRF 令牌,您必须将其与调用一起传递。 显然这会带来很多开销,这不是您想要使用 API.
的方式我要求 API 开发人员提供 OAuth2 身份验证。