是的,我将 csrf 令牌添加到我的表单中,是的,我在表单中添加了 post 方法,是的,我检查了服务器发送 cookie 是否与客户端 cookie 匹配。另外,其他好的上下文可能是我的主页视图上有 loginrequiredMixin,因此在尝试访问它时它会将您重定向到登录页面,但不认为这是问题所在。
Django 说原因是它找不到 csrf 令牌,但我检查了 Django 源代码中的名称,它与密钥匹配,并且具有从服务器发送的匹配值,即
request_csrf_token = request.POST.get("csrfmiddlewaretoken", "")
这是我正在使用的表单,它们继承了 Django 默认注册和登录表单:
class LoginForm(AuthenticationForm):
def __init__(self, request=None, *args, **kwargs):
super(LoginForm, self).__init__(request, *args, **kwargs)
self.fields['username'].widget = forms.TextInput(attrs={'class': 'form-control', 'id': 'username'})
self.fields['password'].widget = forms.PasswordInput(attrs={'class': 'form-control'})
self.fields['remember_me'] = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(attrs={'class': 'custom-control-input', 'id': 'remember-me'})
)
类 SignUpForm(UserCreationForm): 电子邮件 = forms.EmailField(widget=forms.EmailInput(attrs={'class': 'form-control'})) 用户名 = forms.CharField(max_length=100, required=False, widget=forms.TextInput(attrs={'class': 'form-control'})) 密码1 = forms.CharField(label='密码', widget=forms.PasswordInput(attrs={'class': 'form-control'})) password2 = forms.CharField(label='确认密码', widget=forms.PasswordInput(attrs={'class': 'form-control'}))
我在这里迷失了,我做错了什么?
<form method="POST" id="formAuthentication" class="mb-3">
<div class="input-group mb-3">
{{ form.username|attr:"placeholder:Username"|add_class:'form-control' }}
<button id="diceButton" class="btn btn-outline-secondary" type="button" onclick="rollDice()">
<small>🎲</small>
</button>
</div>
<div class="mb-3">
{{ form.email|attr:"placeholder:Email"|add_class:'form-control' }}
</div>
<div class="mb-3">
{{ form.password1|attr:"placeholder:Password"|add_class:'form-control' }}
</div>
<div class="mb-3">
{{ form.password2|attr:"placeholder:Confirm Password"|add_class:'form-control' }}
</div>
<button class="btn btn-primary d-grid w-100">
Sign up
</button>
{% csrf_token %}
</form>
我的 Django 登录视图:
class LoginView(TemplateView):
form_class = LoginForm
template_name = "auth_login_basic.html"
def get_context_data(self, **kwargs):
csrf_token = get_token(self.request)
print("token (server) ", csrf_token)
context = TemplateLayout.init(self, super().get_context_data(**kwargs))
context.update(
{
"layout_path": TemplateHelper.set_layout("layout_blank.html", context),
"form": self.form_class,
"csrf_token": csrf_token,
}
)
return context
def post(self, request, *args, **kwargs):
print("request method: ", request.method)
received_token = request.POST.get('csrfmiddlewaretoken', '')
assert received_token == get_token(request), "CSRF token mismatch"
form = self.form_class(request.POST)
context = self.get_context_data(**kwargs)
context['form'] = form
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(request, username=username, password=password)
if form.cleaned_data.get('remember_me'):
print("Remember me True")
request.session.set_expiry(1209600)
else:
print("Remember me False")
request.session.set_expiry(0)
if user is not None:
login(request, user)
messages.success(request, "Login successful")
return redirect('index')
else:
messages.error(request, "Invalid username or password")
else:
for field, errors in form.errors.items():
for error in errors:
print(f"Error in field '{field}': {error}")
messages.error(request, f"Error in field '{field}': {error}")
return render(request, self.template_name, context)
Django 设置:
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.middleware.locale.LocaleMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ALLOWED_HOSTS = ["localhost"]
ALLOWED_CORS_HOSTS = ["http://localhost"]
CSRF_TRUSTED_ORIGINS = ['http://localhost:8000', "http://127.0.0.1"]
CSRF_COOKIE_SAMESITE = 'None'
CORS_ORIGIN_WHITELIST = (
'http://localhost:8000',
)
确保将 {% csrf_token %} 标签放置在表单的提交按钮之前。
{% csrf_token %}
<button class="btn btn-primary d-grid w-100"> Sign up </button>