2016-04-01 3 views
3

Я использую requests для входа на сайт Django для тестирования (и да, я знаю о Django TestClient, но мне нужен простой http здесь). Я могу войти в систему и, до тех пор, как я делаю , получите запросов, все в порядке.запросы django и python - получение 403 на запрос по почте

Когда я пытаюсь использовать сообщение вместо этого, я получаю 403 от промежуточного программного обеспечения csrf. Я уже работал над этим, используя @crsf_exempt на моем представлении, но предпочел бы более долгосрочное решение.

Это мой код:

with requests.Session() as ses: 

    try: 

     data = { 
      'username': self.username, 
      'password': self.password, 
     } 

     ses.get(login_url) 
     try: 
      csrftoken = ses.cookies["csrftoken"] 
     except Exception, e: 
      raise 
     data.update(csrfmiddlewaretoken=csrftoken) 

     _login_response = ses.post(login_url, data=data) 

     logger.info("ses.cookies:%s" % (ses.cookies)) 

     assert 200 <= _login_response.status_code < 300, "_login_response.status_code:%s" % (_login_response.status_code) 

     response = ses.post(
      full_url, 
      data=data, 
      ) 

     return self._process_response(response) 

Войти работает отлично, и я могу видеть CSRF токен здесь.

INFO:tests.helper_fetch:ses.cookies:<RequestsCookieJar[<Cookie csrftoken=TmM97gnNHs4YCgQPzfNztrAWY3KcysAg for localhost.local/>, <Cookie sessionid=kj6wfmta 

Однако промежуточное ПО видит, что печенье пустует.

INFO:django.middleware.csrf:request.COOKIES:{} 

Я добавил код протоколирования к нему:

def process_view(self, request, callback, callback_args, callback_kwargs): 

    if getattr(request, 'csrf_processing_done', False): 
     return None 

    try: 
     csrf_token = _sanitize_token(
      request.COOKIES[settings.CSRF_COOKIE_NAME]) 
     # Use same token next time 
     request.META['CSRF_COOKIE'] = csrf_token 
    except KeyError: 
     # import pdb 
     # pdb.set_trace() 
     import logging 
     logger = logging.getLogger(__name__) 
     logger.info("request.COOKIES:%s" % (request.COOKIES)) 

я упускаю что-то с образом я называю session.post запрос в? Я попробовал добавить к нему cookie, не имело значения. Но я могу полностью понять, почему crsf-промежуточное программное обеспечение отключается. Я думал, что куки были частью сессии, так почему они не хватает во втором посте?

  response = ses.post(
       self.res.full_url, 
       data=data, 
       cookies=ses.cookies, 
       ) 

Это изменение, вдохновленный How to send cookies in a post request with the Python Requests library?, также не привело ни к чему передается в CSRF промежуточного слоя:

  response = ses.post(
       self.res.full_url, 
       data=data, 
       cookies=dict(csrftoken=csrftoken), 
       ) 

ответ

4

Для последующих запросов после входа в систему, попробуйте поставлять его в качестве заголовка X-CSRFToken вместо этого.

Следующие работал для меня:

with requests.Session() as sesssion: 
    response = session.get(login_url) 
    response.raise_for_status() # raises HTTPError if: 400 <= status_code < 600 

    csrf = session.cookies['csrftoken'] 
    data = { 
     'username': self.username, 
     'password': self.password, 
     'csrfmiddlewaretoken': csrf 
    } 


    response = session.post(login_url, data=data) 
    response.raise_for_status() 

    headers = {'X-CSRFToken': csrf, 'Referer': url} 
    response = session.post('another_url', data={}, headers=headers) 
    response.raise_for_status() 

    return response # At this point we probably made it 

Docs ссылка: https://docs.djangoproject.com/en/dev/ref/csrf/#csrf-ajax

+0

Благодарим за помощь. Получил это нормально, мне пришлось внести некоторые изменения, и это заняло много времени, потому что токен csrf ** изменяется ** после 'session.post (login_url, data = data)'. И этот измененный токен - это то, что нужно переходить в «X-CSRFToken». Но это выглядит довольно хорошо, и X-CSRFToken соответствует тому, что я делаю для сообщений JS Ajax. Я сделаю это, чтобы написать мой ответ в конце недели - с очищенным кодом - и принять ваш ответ, указав мне в правильном направлении. Держать его открытым пока, потому что это была не дешевая щедрость, и у кого-то может быть еще один отличный ответ. Береги себя. –

+0

Если я не принял его к понедельнику, прошу прощения. Я * предполагаю *, что SO все равно будет награждать вас 100 очками, если я превышу продолжительность щедрости, но не хочу, чтобы вы пропустили награду, если это не так. –

+0

Не беспокойтесь о щедрости! Я просто ответил на этот вопрос, потому что мне удалось это решить некоторое время назад. Вы правы, когда токен csrf изменяется после сообщения для входа в систему, но если вы используете сеансы, он обрабатывается прозрачно для вас. Для полного решения не стесняйтесь проверить мою библиотеку на github (которая проверяет контроль доступа) точно так, как вы это делаете: https: // github.com/stphivos/fnval/blob/master/fnval/net.py # L41 – fips

1

Вы также можете попробовать использовать this decorator на ваш взгляд, вместо csrf_exempt. Я попытался воспроизвести вашу проблему, и это сработало для меня.

from django.views.decorators.csrf import ensure_csrf_cookie` 

@ensure_csrf_cookie 
def your_login_view(request): 
    # your view code 
+0

Задача 'обеспечить_csrf_cookie' - убедиться, что токен csrf отключен, даже если на странице нет формы. У меня нет этой проблемы - в моей записи конкретно говорится, что я вижу csrf_token, я просто не знаю, как передать ее обратно в реальный целевой (не входной) POST. –

+0

Хорошо, спасибо за ваш комментарий, самое главное здесь, что вы найдете решение, которое работает для вас;), и что мы, кто хочет помочь в этом, имели это в виду, и это была моя цель;) , Спасибо еще раз и удачи! –

Смежные вопросы