2015-02-09 95 views
0

我有一个管理Users的Django网站。使用内置功能,用户可以从网站请求重置密码,并且效果很好。我已经实施它according to this tutorial,所以我使用the built-in password reset functionalityDjango:在没有CSRF令牌的情况下重置密码

我有一个Android应用程序,用户也应该能够请求重置密码。问题是我没有在应用程序中使用CSRF token,而在the 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中重置密码?或者,从应用程序请求此操作的正确方法是什么?

+0

你知道用户?然后,只需在该功能内向网站发出请求(请参阅http://docs.python-requests.org/en/latest/),而不是执行重定向并将响应返回给请求。这样你就可以把任何你想要的东西放在帖子里。 – mtnpaul 2015-02-09 21:26:31

回答

0

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

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

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

这是我实现了从Android实现这一目标的代码(修整):

​​

GET请求:你想从org.apache.http.clientCookieStore

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; 

注意。

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();