Android的HTTP POST请求的Django升级到1.6后,将返回403 [英] Android http post request returns 403 after Django update to 1.6

查看:672
本文介绍了Android的HTTP POST请求的Django升级到1.6后,将返回403的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个Android应用程序将数据发送JSON格式到本地服务器上运行Django的REST API。这是一个HTTPS连接到服务器和所有必要的证书integratted到应用程序。 Bevore我们已经更新到1.6的Django对我们的Django 1.4正在运行,一切运行良好。现在使用Django 1.6应用程序仍然能够得到CSRF令牌,登录并做了HTTPGET请求时,它返回预期的JSON对象。只有HttpPost请求被拒绝,403禁止。我搜索通过网络,只发现了跨​​站请求伪造保护可能是一个问题,但我们正在访问通过web浏览器和应用程序的API,所以我认为这将是一个安全的缺乏将其关闭。

I'm writing an Android app which sends data in JSON format to a Django REST API running on a local server. It is an https connection to the server and all necessary certificates are integratted into the app. Bevore we've updated to Django 1.6 we were running on Django 1.4 and everything worked fine. Now with Django 1.6 the app is still able to get the CSRF token, to log in and to do a HttpGet request, which returns the expected JSON object. Only the HttpPost requests are rejected with 403 Forbidden. I searched through the web and only found out that the Cross Site Request Forgery protection could be a problem, but we are accessing the API via webbrowser and app, so I think it would be a security lack to turn it off.

下面是我做的,开始httpPost和HTTPGET:

Here is what I do to start httpPost and HttpGet:

在启动应用程序后的H​​ttpClient拿着服务器证书被创建,比用这一个对所有GET和POST请求:

After starting the app a HttpClient holding the server certificates is created, this one is than used for all get and post requests:

private DefaultHttpClient createHttpClient(Context ctx) throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException, UnrecoverableKeyException
{
    SSLSocketFactory ssf = new SSLSocketFactory(keyStore);

    SchemeRegistry schemeRegistry = new SchemeRegistry();

    // http scheme
    schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 888));
    // https scheme
    schemeRegistry.register(new Scheme("https", ssf, 443));

    HttpParams params = new BasicHttpParams();

    params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, true);
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    HttpProtocolParams.setContentCharset(params, "utf-8");

    //ClientConnectionManager cm = 
        //    new ThreadSafeClientConnManager(params, schemeRegistry);
    ClientConnectionManager cm = 
           new SingleClientConnManager(params, schemeRegistry);

    return new DefaultHttpClient(cm, params);

}

然后我发送一个GET请求来获取CSRF令牌和登录算账:

Then I send a get request to get the CSRF token and login afterwards:

public static String openAuthStream(DefaultHttpClient httpClient, String u, String pw) throws ClientProtocolException, IOException
{
    // defaultHttpClient        
    HttpGet httpGet = new HttpGet(Constants.LOGIN_URL);

    httpClient.execute(httpGet);

    String csrfToken = new String();
    CookieStore cookieStore = httpClient.getCookieStore();
    List <Cookie> cookies =  cookieStore.getCookies();
    for (Cookie cookie: cookies) {
        if (cookie.getDomain().equals(Constants.CSRF_DOMAIN) && cookie.getName().equals("csrftoken")) {
            csrfToken = cookie.getValue();
        }
    }        
    httpGet.setHeader("Referer", Constants.LOGIN_URL);
    httpGet.setHeader("X-CSRFToken", csrfToken);

    //httpGet.abort();

    List<NameValuePair> credentials = new ArrayList<NameValuePair>();  
    credentials.add(new BasicNameValuePair("username", u)); 
    credentials.add(new BasicNameValuePair("password", pw)); 

    HttpPost post = new HttpPost(Constants.LOGIN_URL);
    post.setHeader("Referer", Constants.LOGIN_URL);
    post.setHeader("X-CSRFToken", csrfToken);       
    post.setEntity(new UrlEncodedFormEntity(credentials));

    HttpResponse response = httpClient.execute(post);
    //post.abort();

    if(response.getStatusLine().getStatusCode() == 200)
        return csrfToken;

    return null;
}

最后的POST请求是通过这种方式建立:

Finally the post requests is build up in this way:

public HttpResponse sendJSONToUrl(DefaultHttpClient httpClient,String url, String csrfToken, JSONObject json) {
    try {   
        HttpPost httpPostJson = new HttpPost(url);
        httpPostJson.setEntity(new StringEntity(json.toString(),HTTP.UTF_8));
        httpPostJson.setHeader("Referer", url);
        httpPostJson.setHeader("X-CSRFToken", csrfToken);
        httpPostJson.setHeader("Accept", "application/json");
        httpPostJson.setHeader("Content-type", "application/json");
        HttpResponse response = httpClient.execute(httpPostJson);
        httpPostJson.abort();  

        return response;

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

一切都工作得很好的Django的1.4,现在我很无奈。
在此先感谢!

Everything worked fine on Django 1.4 and now I'm helpless. Thanks in advance!

推荐答案

解决了问题。 sucessfull登录后CSRF令牌的变化(什么不能使用Django 1.4 happend),所以POST后登录信息的另一个GET已提出,要获得新令牌CSRF,然后一切正常像以前一样。感谢所有帮助!

Solved the problem. The CSRF token changes after sucessfull login ( what not happend with Django 1.4 ), so after POST with login information another GET has to be made to get the new CSRF token and then everything works fine like before. thanks for all the help!

这篇关于Android的HTTP POST请求的Django升级到1.6后,将返回403的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆