在Django中处理CSRF令牌

时间:2013-05-10 10:33:28

标签: django python-2.7

我写了一个小的独立python脚本,它调用我的基于django的后端,一切正常,登录和调用需要auth的视图等等。

一些代码

def dostuff():
    session = login(username, password)
    license = add_license(session)

def _helper(self, url, cookie=None):
    http = httplib2.Http()
    if cookie:
        headers = { "Cookie" : cookie }
    else:
        headers = {}
    response, content = http.request(host + url, "GET", headers=headers, body="")
    return response, content

def login(self, username, password):
    url = "/license/login?username=%s&password=%s" % (username, password)
    response, content = self._helper(url)
    sessioncookie = response["set-cookie"]
    customer_id = re.search("id=(?P<id>\d+)", content)
    if response["status"] == "200":
        return sessioncookie, customer_id.group("id")

def add_license(self, session):
    cookie = session[0]
    customer_id = int(session[1])-1
    url = "/license/add_license?customer_id=%s" % customer_id
    response, content = self._helper(url, cookie)
    content = content[1:-1]
    if response["status"] == "200": #ok
        data = json.loads(content)
        return data["fields"]

如果我将“GET”改为“POST”,我会遇到Django CSRF错误页面(CSRF验证失败)。如何将POST数据发送到Django?

我在Django中的登录视图,我是否需要做一些特殊的事情来添加csrf令牌?我的计划是重写这个,以便在事情正常时发送json。

 def my_login(request):
    done, username = get_input(request, "username")
    if not done:
        return username
    done, password = get_input(request, "password")
    if not done:
        return password
    user = authenticate(username=username, password=password)
    if user is not None:
       if user.is_active:
            login(request, user)
            return HttpResponse("Done, id=%s" % user.pk)
        else:
            return HttpResponse("User disabled")
    else:
        return HttpResponse("Invalid login")

3 个答案:

答案 0 :(得分:1)

我得到了它的工作,这就是我做到的。就像toto_tico建议的那样,我转动了一个虚拟视图,我检索了GET来获取CSRF令牌。起初它没有通过GET发送csrf令牌,所以我不得不添加装饰器ensure_csrf_cookie。

@ensure_csrf_cookie
def dummy(request):
    return HttpResponse("done")

然后我正常处理登录请求。

def my_login(request):
    ...handle login...

事实证明,仅仅将cookie添加到POST是不够的,我还必须为POST数据写一个令牌。

def _helper(self, url, method="POST"):
    req = urllib2.Request(host + url)
    self.cookieMgr.add_cookie_header(req)
    try:
        if method == "GET":
            response = self.opener.open(req)
        else:
            for cookie in self.cookieMgr:
                if cookie.name == "csrftoken":
                    csrf = cookie.value
            values = { "csrfmiddlewaretoken" : csrf}
            params = urllib.urlencode(values)
            response = self.opener.open(req, params)
            code = response.getcode()
            info = response.info()
            content = response.read()
            return code, info, content
    except urllib2.HTTPError as ex:
        print str(ex)
        sys.exit(1)

def get_csrf(self):
    url = "/license/dummy"
    self._helper(url, method="GET")

def login(self, username, password):
    self.get_csrf()
    url = "/license/login?username=%s&password=%s" % (username, password)
    code, info, content = self._helper(url)
    if code == 200:
        #done!

答案 1 :(得分:0)

当您向Django发出请求时,您必须添加csrftoken cookie值。或者,您可以将@csrf_exempt添加到Django后端以接受这些请求。

答案 2 :(得分:0)

开始阅读CSFR and ajax。我通常使用提供的代码执行以下操作:

  1. 创建csfr.js文件
  2. the code粘贴到csfr.js文件
  3. 引用需要它的模板中的代码|

  4. 如果你正在使用模板并且有类似base.html的东西,那么你可以从那里引用脚本,你不必再担心其余的编程了。据我所知,这不应该代表任何安全问题。