【问题标题】:Django: resetting password without a CSRF tokenDjango:在没有 CSRF 令牌的情况下重置密码
【发布时间】:2015-04-09 16:59:48
【问题描述】:

我有一个管理 Users 的 Django 网站。使用内置功能,用户可以从网站请求密码重置,效果很好。我已经实现了它according to this tutorial,所以我正在使用the built-in password reset functionality

我有一个 Android 应用,用户也应该可以通过该应用请求重置密码。问题是我在应用程序中没有CSRF tokenthe built-in password_reset method has the @csrf_protect decorator。这意味着我无法在没有 CSRF 令牌的情况下访问它,也无法使用 @csrf_exempt 装饰器对其进行修改。

所以下一个想法是创建一个函数,它生成一个 CSRF 令牌,将其存储在请求中并重定向到发送重置电子邮件的正确 URL。问题是according to this, django does not allow to pass POST parameters further in a redirect

因此我的问题是如何在没有 CSRF 令牌的情况下在 Django 中请求重置密码?或者,从应用程序请求此信息的正确方法是什么

【问题讨论】:

  • 你认识这个用户吗?然后只需在函数内向站点发出请求(请参阅docs.python-requests.org/en/latest),而不是执行重定向并返回对请求的响应。这样你就可以在帖子中放任何你想要的。

标签: android django django-users django-csrf forgot-password


【解决方案1】:

我自己找到了解决方案。请随时发布任何替代解决方案。不需要两个单独请求的请求会特别好。

如果您查看the password_reset method,您可以看到它仅在请求方法为 POST 的情况下尝试将请求作为重置请求处理。否则它只会返回一个包含表单的TemplateResponse。这也包含作为 cookie 的 CSRF 令牌。

首先,我向http://myaddress.com/user/password/reset/ 发送一个GET 请求,并从响应中提取CSRF cookie。然后我发送一个 POST 请求,其中包含 cookie、电子邮件地址和 2 个标头(见下文)。

这是我从Android(修剪)实现的代码:

String url = "http://myaddress.com/user/password/reset/";

GET 请求:

HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
CookieStore cookieStore = new BasicCookieStore();
HttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpResponse httpResponse = httpClient.execute(httpGet, localContext);

Cookie csrfCookie = null;
for (Cookie cookie : cookieStore.getCookies()) {
    if (cookie.getName() == "csrftoken") {
        csrfCookie = cookie;
        break;
    }
}

if (csrfCookie == null) {
    throw new NullPointerException("CSRF cookie not found!");
}

return csrfCookie;

请注意,您需要来自org.apache.http.clientCookieStore

POST 请求:

HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);

// Prepare the cookie store to receive cookies.
CookieStore cookieStore = new BasicCookieStore();
cookieStore.addCookie(csrfCookie);
httpPost.setHeader("Referer", url);
httpPost.setHeader("X-CSRFToken", csrfCookie.getValue());
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addTextBody("email", emailAddressToReset);
httpPost.setEntity(builder.build());

HttpResponse httpResponse = httpClient.execute(httpPost, localContext);
if (httpResponse.getStatusLine().getStatusCode() != 200) {
    throw new Exception("Could not reset password!");
}

Toast.makeText(context, "Password reset requested! Please check your email inbox!", Toast.LENGTH_LONG).show();

【讨论】:

    猜你喜欢
    • 2015-10-02
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 2021-06-17
    • 1970-01-01
    相关资源
    最近更新 更多