如何修复Django中登录失败后CSRF TOKEN被表单数据覆盖的问题?
多租户项目登录表单异常:登录失败后CSRF Token与username字段被密码覆盖
我使用django-tenant和django-tenant-user构建多租户项目时遇到异常:登录尝试失败后,登录表单的CSRF Token与username字段会被密码数据覆盖。已尝试打印表单数据排查,但未找到根源——首次请求CSRF Token传递正常,后续请求中密码数据会被当作CSRF Token传递。
相关代码片段
View
def login_user(request): if request.user.is_authenticated: return redirect('core:index') if request.method != 'POST': form = LoginForm() return render(request, 'core/login.html', {'form': form}) form = LoginForm(request.POST) if not form.is_valid(): context = {"form": form} if not form.errors: messages.error(request, 'Invalid username or password') return render(request, 'core/login.html', context) user = authenticate(request, username=form.cleaned_data['username'], password=form.cleaned_data['password']) if user is None: messages.error(request, 'Invalid username or password.') return render(request, 'core/login.html', {'form': form}) messages.success(request, 'Login successful') login(request, user) return redirect('core:index')
Form
class LoginForm(forms.Form): username = forms.CharField(min_length=4, max_length=150) password = forms.CharField(min_length=4, max_length=128, widget=forms.PasswordInput)
Template
{% extends "_base.html" %} {% block title %} <title>TalwaPro HR Admin - Login </title> {% endblock title %} {% block content %} {% load tailwind_filters %} <div class="flex h-screen items-center justify-center"> <div class="card w-[90%] bg-base-200 shadow-xl justify-center md:w-[65%] lg:w-[40%]"> {% if messages %} <div class="toast toast-top toast-start"> <div class="alert alert-error"> {% for message in messages %} {{ message }} {% endfor %} </div> </div> {% endif %} <div class="card-body"> <h2 class="card-title text-accent justify-center">Sign In</h2> <form class="mt-4" action="/login/" method="POST"> {% csrf_token %} <label class="input input-bordered flex items-center gap-2 {% if form.username.errors %} border-error {% endif %}"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-4 h-4 opacity-70"><path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12.735 14c.618 0 1.093-.561.872-1.139a6.002 6.002"></path></svg> <input type="text" class="grow" name="username" value="{% if form.username.value %} {{form.username.value}} {% endif %}" placeholder="Username" required /> </label> <div class="text-error"> {% if form %} {{ form.username.errors }} {% endif %} </div> <label class="input input-bordered flex items-center gap-2 mt-4 {% if form.password.errors %} border-error {% endif %}"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-4 h-4 opacity-70"><path fill-rule="evenodd" d="M14 6a4 4 0 0 1-4.899 3.899l-1.955 1.955a.5.5 0 0 1-.353.146H5v1"></path></svg> <input type="password" class="grow" name="password" placeholder="Password" required /> </label> <div class="text-error"> {% if form %} {{ form.password.errors }} {% endif %} </div> <div class="card-actions justify-center mt-4"> <button class="btn btn-primary" type="submit">Sign In</button> </div> </form> </div> </div> </div> {% endblock %}
问题根源与解决方案
问题根源
模板中的<svg>标签未正确闭合,导致HTML结构解析错乱。浏览器在处理未闭合标签时,会错误地将后续表单元素(包括CSRF Token隐藏字段)纳入SVG标签范围,进而引发表单数据提交时的字段值覆盖问题。
解决方案
修复未闭合的SVG标签
给每个<svg>标签添加闭合的</svg>标签,确保HTML结构完整。修正后的示例:<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-4 h-4 opacity-70"> <path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12.735 14c.618 0 1.093-.561.872-1.139a6.002 6.002"></path> </svg>改用Django表单内置渲染方式
避免手动编写表单输入字段,使用Django表单的字段渲染语法,结合tailwind_filters简化样式处理,同时避免手动HTML的结构错误:{{ form.username|add_class:"grow" }} {{ form.password|add_class:"grow" }}验证HTML结构
修复后通过浏览器开发者工具检查页面HTML结构,确认所有标签闭合正常,CSRF Token隐藏字段位于表单内正确位置。
内容的提问来源于stack exchange,提问作者Maxwell D. Dorliea
相关产品推荐
相关产品推荐

