django和python请求-在post请求中获得403

django和python请求-在post请求中获得403,django,python-requests,django-csrf,Django,Python Requests,Django Csrf,我正在使用请求登录到我的Django站点进行测试(是的,我知道Django TestClient,但我在这里需要纯http)。我可以登录,只要我做获取请求,一切都可以 当我尝试使用post时,我从csrf中间件获得了403。在我看来,我已经通过使用@crsf_豁免解决了这个问题,但我更喜欢一个长期的解决方案 这是我的代码: with requests.Session() as ses: try: data = { 'username': sel

我正在使用
请求
登录到我的Django站点进行测试(是的,我知道Django TestClient,但我在这里需要纯http)。我可以登录,只要我做获取请求,一切都可以

当我尝试使用post时,我从csrf中间件获得了403。在我看来,我已经通过使用@crsf_豁免解决了这个问题,但我更喜欢一个长期的解决方案

这是我的代码:

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)
我已将日志代码添加到其中:

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的方式是否遗漏了什么?我试着把饼干加进去,没什么区别。但我完全可以理解为什么crsf中间件会出问题。我以为这些饼干是会议的一部分,那么为什么它们在我的第二篇文章中不见了呢

            response = ses.post(
                self.res.full_url,
                data=data,
                cookies=ses.cookies,
                )
这一变化的灵感来自于,也没有导致任何东西被传递到csrf中间件:

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

对于登录后的后续请求,请尝试将其作为标头
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
将requests.Session()作为Session的
:
response=session.get(登录\ url)
response.raise_for_status()#如果:400您也可以尝试在视图中使用,而不是
csrf_豁免
,则会引发HTTPError。我试图复制你的问题,这对我来说也很有效

from django.views.decorators.csrf import ensure_csrf_cookie`

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

确保\u csrf\u cookie
任务是确保csrf令牌熄灭,即使页面上没有表单。我没有这个问题-我的文章特别提到我可以看到csrf_令牌,我只是不知道如何将它传递回实际的目标(而不是登录)帖子。好的,谢谢你的评论,这里最重要的是你找到一个适合你的解决方案;),而我们这些希望帮助实现这一目标的人,也将这一点铭记在心,这是我的目标;)。再次感谢,祝你好运!谢谢你的帮助。让它正常工作,我必须做一些更改,这需要很长时间才能弄清楚,因为csrf令牌在
会话.post(login\u url,data=data)
之后会发生更改。而更改后的令牌需要进入
X-CSRFToken
。但它看起来相当不错,X-CSRFToken与我为jsajax帖子所做的匹配。我要做的是在周末写下我的答案——用清理过的代码——并接受你的答案,因为它为我指明了正确的方向。保持开放,因为这不是一个便宜的赏金,有人可能会有另一个伟大的答案。保重。如果星期一我还没有接受,给我打个电话。如果我超过了赏金期限,我想SO仍然会给你100分,但如果不是这样,我不想让你错过赏金。不要担心赏金!我刚才回答了这个问题,因为我刚才碰巧解决了这个问题。您是对的,csrf令牌在post登录后会发生更改,但如果您使用会话,则会对您进行透明的处理。要获得完整的解决方案,请按照您的方式在github上查看我的库(进行访问控制检查):奖金是不可退还的,所以我已经为此支付了费用。还不如奖励它。是的,也许sessions应该处理好,但是没有。或者至少看起来没有。此外,我还看到有人在其他地方评论说,有时候
请求
的会话会让cookie从裂缝中掉落。有趣的是,有时写30行代码(这项工作)可能需要几天;-)好主意,
fnval
。我正在做一些可能与此有关的事情。django测试用例在TestClient上运行,激发一个包含一些数据的URL,然后您可以解析响应。但是它们只对本地测试客户机有效,即使实际上大部分工作都是定义测试参数和针对响应运行的unittest断言。我的代码重用了所有这些,但使用
请求
对任意主机名+端口启动它。在我的例子中,我最想做的就是测试一个基于VM的设备。每次url调用我都会登录,所以会话没什么大不了的。
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
from django.views.decorators.csrf import ensure_csrf_cookie`

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