Android отправляет почтовые запросы серверу django csrf не удается - PullRequest
10 голосов
/ 13 февраля 2012

Я бы хотел, чтобы мое приложение для Android могло отправлять некоторую информацию на мой сервер django.Поэтому я заставил приложение для Android отправить запрос на страницу mysite / upload, и представление django для этой страницы будет работать на основе данных публикации.Проблема в том, что сервер дает ответ на почтовый запрос, который жалуется на неудачу проверки csrf.Если посмотреть на проблему, мне кажется, что мне, возможно, придется сначала получить токен csrf с сервера, а затем выполнить публикацию с этим токеном.Редактировать: я обнаружил, что могу сбросить проверку crsf для этого представления с помощью декоратора представления @csrf_exempt, но я не уверен, что это лучшее решениеКод моего Android:

// Create a new HttpClient and Post Header
                    HttpClient httpclient = new DefaultHttpClient();
                    HttpPost httppost = new HttpPost(URL);

                    // Add your data
                    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
                    nameValuePairs.add(new BasicNameValuePair("scoreone", scoreone));
                    nameValuePairs.add(new BasicNameValuePair("scoretwo", scoretwo));
                    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                    System.out.println("huzahhhhhhh");
                    // Execute HTTP Post Request
                    HttpResponse response = httpclient.execute(httppost);
                    BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                    StringBuffer sb = new StringBuffer("");
                    String line = "";
                    String NL = System.getProperty("line.separator");
                    while ((line = in.readLine()) != null) {
                        sb.append(line + NL);
                    }
                    in.close();
                    String result = sb.toString();
                    System.out.println("Result: "+result);

и код моего просмотра для загрузки:

# uploads a players match
def upload(request):
    if request.method == 'POST':
        scoreone = int(request.POST['scoreone'])
        scoretwo = int(request.POST['scoretwo'])
        m = Match.objects.create()
        MatchParticipant.objects.create(player = Player.objects.get(pk=1), match = m, score = scoreone)
        MatchParticipant.objects.create(player = Player.objects.get(pk=2), match = m, score = scoretwo)
    return HttpResponse("Match uploaded" )

enter code here

Ответы [ 3 ]

10 голосов
/ 24 июня 2013

Сначала вам нужно прочитать токен csrf из файлов cookie из запроса на предварительный просмотр:

httpClient.execute(new HttpGet(uri));
CookieStore cookieStore = httpClient.getCookieStore();
List <Cookie> cookies =  cookieStore.getCookies();
for (Cookie cookie: cookies) {
    if (cookie.getDomain().equals(Constants.CSRF_COOKIE_DOMAIN) && cookie.getName().equals("csrftoken")) {
        CSRFTOKEN = cookie.getValue();
    }
}

Если ваше представление не отображает шаблон, содержащий csrf_token Шаблонный тег, Django может не установить cookie-токен CSRF. Это обычно в случаях, когда формы динамически добавляются на страницу. к В этом случае Django предоставляет декоратор вида, который заставляет настройка файла cookie: sure_csrf_cookie (). - https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

Затем вы можете передать его на сервер по заголовкам почтового запроса и куки при выполнении почтового запроса:

httpPost.setHeader("Referer", Constants.SITE_URL);
httpPost.setHeader("X-CSRFToken", CSRFTOKEN);

DefaultHttpClient client = new DefaultHttpClient();
final BasicCookieStore cookieStore =  new BasicCookieStore();

BasicClientCookie csrf_cookie = new BasicClientCookie("csrftoken", CSRFTOKEN);
csrf_cookie.setDomain(Constants.CSRF_COOKIE_DOMAIN);
cookieStore.addCookie(csrf_cookie);

// Create local HTTP context - to store cookies
HttpContext localContext = new BasicHttpContext();
// Bind custom cookie store to the local context
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

HttpResponse response = client.execute(httpPost, localContext);
2 голосов
/ 13 июля 2012

Отключение проверки CSRF, безусловно, работает! но вы уверены, что хотите это сделать? ваш оригинальный образ мышления; получить токен с сервера и отправить его вместе с данными POST намного лучше.

Маркер csrf обычно присутствует в форме файла cookie. Например, в инфраструктуре Django у вас есть файл cookie с именем csrftoken, вам нужно получить это значение и отправить его на сервер как «X-CSRFToken»

2 голосов
/ 13 февраля 2012

Напишите собственный декоратор и добавьте «секретный» заголовок к вашему запросу. https://code.djangoproject.com/browser/django/trunk/django/views/decorators/csrf.py

def csrf_exempt(view_func):
        """
        Marks a view function as being exempt from the CSRF view protection.
        """
        # We could just do view_func.csrf_exempt = True, but decorators
        # are nicer if they don't have side-effects, so we return a new
        # function.
        def wrapped_view(request,*args, **kwargs):
            return view_func(request, *args, **kwargs)
            if request.META.has_key('HTTP_X_SKIP_CSRF'):
                wrapped_view.csrf_exempt = True
        return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...