请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

这一节的login表单中点击提交提示CSRF验证失败

1.环境:

win10,django 2.1.2,Mako 1.1.0

2.问题现象:

9-4小节一分零三秒之前的dashboard 的代码功能实现都正常。

login 页面 get 方法显示正常,测试填写用户名和密码后,点击提交出现报错页面:

https://img1.sycdn.imooc.com/szimg/5de239cb085f8ddb07840138.jpg

3.错误代码:

(1)app\dashboard\views\auth.py:

from django.shortcuts import redirect
from django.views.generic import View
from app.libs.base_render import render_to_response

class Login(View):
    TEMPLATE = 'dashboard/auth/login.html'

    def get(self, request):
        return render_to_response(request, self.TEMPLATE)

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        print(username, password)
        return redirect('/dashboard/login')

(2)templates\dashboard\auth\login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login | 登录</title>
    <link href="/static/dashboard/css/bootstrap.min.css" rel="stylesheet" />
    <link rel="stylesheet" href="/static/dashboard/css/login.css">
</head>
<body>
<form class="form-horizontal edit-area" action="login" method="POST">
  <div class="form-group">
  <div class="col-sm-10">
    <input type="text" name="username" class="form-control" placeholder="用户名">
  </div>
  </div>
  <div class="form-group">
  <div class="col-sm-10">
    <input type="password" name="password" class="form-control" placeholder="密码">
  </div>
  </div>
  <div class="form-group">
      <div class="col-sm-offset-2 colsm-10">
          <button type="submit" class="btn btn-default">登录</button>
      </div>
  </div>
</form>
</body>
</html>

(3)app\libs\base_renderr.py

from mako.lookup import TemplateLookup
from django.template import RequestContext
from django.conf import settings
from django.template.context import Context
from django.http import HttpResponse


def render_to_response(request, template, data=None):
    """与jinjia2不同,mako的模板需要自己定义,于是有了本页的代码"""
    context_instance = RequestContext(request)
    path = settings.TEMPLATES[0]['DIRS'][0]

    lookup = TemplateLookup(
        directories=[path],
        output_encoding='utf-8',
        input_encoding='utf-8',
    )

    mako_template = lookup.get_template(template)

    if not data:
        data = {}

    if context_instance:
        context_instance.update(data)
    else:
        context_instance = Context(data)

    result = {}

    for d in context_instance:
        result.update(d)

    result['csrf_token'] = (
        '<input type="hidden" '
        'name="csrfmiddlewaretoken" '
        'value="{0}" />'.format(
            request.META.get('CSRF_COOKIE', '')),)

    return HttpResponse(mako_template.render(**result))



正在回答

4回答

#按照老师的方法已经解决了,以下是代码

from django.conf import settings
from django.http import HttpResponse
from django.middleware.csrf import get_token
from django.template import RequestContext
from django.template.context import Context
from mako.lookup import TemplateLookup

def render_to_response(request, template, data=None):
   context_instance = RequestContext(request)
   path = settings.TEMPLATES[0]['DIRS'][0]
   lookup = TemplateLookup(
       directories=[path],
       output_encoding='utf-8',
       input_encoding='utf-8'
   )   mako_template = lookup.get_template(template)   
   if not data:
       data = {}   
   if context_instance:
       context_instance.update(data)
   else:
       context_instance = Context(data)   result = {}   for d in context_instance:
       result.update(d)
   result['request'] = request
   request.META["CSRF_COOKIE"] = get_token(request)
   result['csrf_token'] = ('<div style="display:none">'
                           '<input type="hidden" '
                           'name="csrfmiddlewaretoken" '
                           'value="{0}"/>'
                           '</div>'.format(request.META["CSRF_COOKIE"]))   
   return HttpResponse(mako_template.render(**result))


5 回复 有任何疑惑可以回复我~
  • 谢谢帮助~我没在电脑旁 所以不方便我复制粘贴~
    回复 有任何疑惑可以回复我~ 2019-11-30 20:52:32
  • 提问者 追蝴蝶的少年ww #2
    可以了,在login.thml里再引用下${csrf_token}。就可以正常post了,非常感谢!
    回复 有任何疑惑可以回复我~ 2019-11-30 21:05:50
  • CD和光同尘 回复 提问者 追蝴蝶的少年ww #3
    还是出现错误呢
    回复 有任何疑惑可以回复我~ 2019-12-11 23:54:29
阿君的猫 2020-07-28 23:59:24

我最近在学,也遇到了问题,刚刚找到了一个很好的解决方法

在重构mako的render中导入一个模块

from django.template.context_processors import csrf

result['csrf_token'] = ('<div style="display:none">'

                           '<input type="hidden" '

                           'name="csrfmiddlewaretoken" '

                           'value="{0}"/>'

                           '</div>'.format(request.META["CSRF_COOKIE"]))  

这句改为下面的:

result['csrf_token'] = '<input type="hidden" id="django-csrf-token" name="csrfmiddlewaretoken" value={0} />'.format(csrf(request)["csrf_token"])


就可以解决了,我发现csrf(request)["csrf_token"]是一个加密的串,也就是csrf的串

3 回复 有任何疑惑可以回复我~
慕虎4249352 2020-05-23 18:49:45

login.html中添加${csrf_token}可以解决,但页面上又多出了一个('',)

https://img1.sycdn.imooc.com//szimg/5ec8ffc709ee0d3f06460334.jpg

0 回复 有任何疑惑可以回复我~
deweizhang 2019-11-30 20:23:30

这个问题可以到群里和大家聊一下 我今天下午已经给出了解决方案 这应该是django的一个bug

0 回复 有任何疑惑可以回复我~
  • 提问者 追蝴蝶的少年ww #1
    if "CSRF_COOKIE" not in request.META:
            csrf_secret = _get_new_csrf_string()
            request.META = _salt_cipher_secret(csrf_secret)
        else:
            csrf_secret = _unsalt_cipher_token(request.META("CSRF_COOKIE"))
        request.META["CSRF_COOKIE_USED"] = True
        return _salt_cipher_secret(csrf_secret)
    这段代码应该插入到base_render的什么位置呀?result['csrf_token']之前?还是替换最后的 return HttpResponse?
    回复 有任何疑惑可以回复我~ 2019-11-30 20:25:54
  • deweizhang 回复 提问者 追蝴蝶的少年ww #2
    只要调用get_token方法就好了~你在群里吧,刚刚有同学试验没问题也截图了 你可以看下~
    回复 有任何疑惑可以回复我~ 2019-11-30 20:26:59
  • 提问者 追蝴蝶的少年ww #3
    我觉得老师可以有空了贴一段后面完整的base_render代码,后面有其他同学在提问区看到就可以直接复用了。
    回复 有任何疑惑可以回复我~ 2019-11-30 20:28:07
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信