我对 Django 还是很陌生,并且设法创建了自己的登录页面,该页面与轴和 repatcha 集成,基本上在 3 次登录尝试失败时显示验证码以及我自己的错误消息 - 这一切都可以正常工作,但我现在也想添加我已经实施的两因素身份验证。
我已经设法安装了 django 两因素身份验证包,但似乎我被迫使用两因素身份验证包附带的登录页面。在我自己的登录和附加功能上花费了这么多时间后,我迫切需要保持这一点。我相信我能够编辑两个因素身份验证模板文件,但主要问题是能够将现有视图/装饰器中的功能与两个因素身份验证视图一起使用。
以下是我当前的设置:
网址
from django.urls import path, include
from . import views
urlpatterns = [
path('login/', views.loginpage, name="login"),
path('logout/', views.logoutuser, name="logout"),
...,
]
看法
@axes_dispatch
@check_recaptcha_login
def loginpage(request, credentials: dict = None):
attempts_list = get_user_attempts(request, credentials)
attempt_count = max(
(
attempts.aggregate(Sum("failures_since_start"))[
"failures_since_start__sum"
]
or 0
)
for attempts in attempts_list
)
#print(attempt_count)
attempt_count = attempt_count
context = {'attempt_count': attempt_count}
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
if user.is_active and attempt_count < 3:
login(request, user)
return redirect('home')
elif user.is_active and request.recaptcha_is_valid:
login(request, user)
return redirect('home')
if not user.is_active:
messages.error(request, 'Account for this User has not been Activated.')
else:
messages.error(request, 'Username or Password is Incorrect.')
#print(context)
return render(request, 'login.html', context)
装饰器(用于验证码)
from django.conf import settings
from django.contrib import messages
from django.db.models import Sum
from functools import wraps
from axes.attempts import (
get_user_attempts,
)
import requests
def check_recaptcha_login(view_func, credentials: dict = None):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
attempts_list = get_user_attempts(request, credentials)
attempt_count = max(
(
attempts.aggregate(Sum("failures_since_start"))[
"failures_since_start__sum"
]
or 0
)
for attempts in attempts_list
)
print(attempt_count)
attempt_count = attempt_count
request.recaptcha_is_valid = None
if request.method == 'POST':
recaptcha_response = request.POST.get('g-recaptcha-response')
data = {
'secret': settings.RECAPTCHA_PRIVATE_KEY,
'response': recaptcha_response
}
r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data)
result = r.json()
if result['success']:
request.recaptcha_is_valid = True
else:
request.recaptcha_is_valid = False
if attempt_count > 2:
messages.error(request, 'Invalid reCAPTCHA. Please try again.')
return view_func(request, *args, **kwargs)
return _wrapped_view
模板
{% extends 'base.html' %}
{% block title %}
{% if request.path == adminpage %}
Admin Login
{% else %}
User Login
{% endif %}
{% endblock %}
{#{% block title %}User Login{% endblock %}#}
{% block content %}
<div class="d-flex justify-content-center">
{% if request.path == adminpage %}
<h3 id="form-title">Admin Login</h3>
{% else %}
<h3 id="form-title">User Login</h3>
{% endif %}
</div>
<div class="d-flex justify-content-center form_container">
<form method="POST" action="">
{% csrf_token %}
<div align="center">
<div class="input-group mb-2">
<div class="input-group-append">
<span class="input-group-text"><i class="fas fa-user"></i></span>
</div>
<input type="text" name="username" placeholder="Email" class="form-control">
</div>
<div class="input-group mb-3">
<div class="input-group-append">
<span class="input-group-text"><i class="fas fa-key"></i></span>
</div>
<input type="password" name="password" placeholder="Password" class="form-control">
</div>
</div>
{% if attempt_count > 1 %}
{% include 'recaptcha.html' %}
{% endif %}
<div class="d-flex justify-content-center mt-3 login_container">
<input class="btn login_btn" type="submit" value="Login">
</div>
</form>
</div>
{% include 'messages.html' %}
<div class="input-group mb-1">
</div>
<div class="mt-1">
{% if request.path == adminpage %}
{% else %}
<div class="d-flex justify-content-center links">
Don't have an account? <a href="{% url 'register' %}" class="ml-2">Sign Up</a>
</div>
{% endif %}
<div class="d-flex justify-content-center links">
Forgot Password? <a href="{% url 'request-password' %}" class="ml-2">Reset Password</a>
</div>
</div>
{% endblock content %}
我的管理员页面也有这个设置,并添加了对 is_staff 的验证(授权使用管理员) - 我没有包括与上面几乎相同的内容,一旦我知道如何实现上述内容,应该能够适应. 如果有人可以指导我如何将上面提到的登录页面功能与两因素身份验证包一起使用,我将不胜感激,因为我目前迷路了。谢谢