AutoRedirect пользователь, чтобы изменить пароль экрана в Django
У меня есть модель профиля пользователя, как показано ниже
class UserProfile(models.Model):
user = models.OneToOneField(User)
role = models.ForeignKey(Role)
.........
.........
password_changed = models.DateTimeField(blank=True, null=True)
у меня есть PASSWORD_EXPIRATION
настройки в settings.py, на основе которых я должен перенаправить пользователя на экран смены пароля, например, если password_changed
дата для пользователя превышает PASSWORD_EXPIRATION
затем перенаправьте пользователя на экран смены пароля
Так что сейчас у меня есть три условия для реализации
1. If the password_changed date was empty,redirect the user to password change screen
2. If the password_changed date exists for the user and if it exceeds PASSWORD_EXPIRATION setting then redirect the user to password change screen
3. Don't let the user access other screens/urls if the password expires/without changing the passwords and redirect to password change screen
Для первых двух пунктов я реализовал в login
метод, как показано ниже
def login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username = username, password = password)
if user is not None and user.is_active:
try:
profile = UserProfile.objects.get(user=user)
# If password_changed date does not exists, redirect to password change screen
if not profile.password_changed:
auth_login(request, user)
return redirect('change_password')
# If password_changed date exists, calculate the expiry date and redirect accordingly
..............
..............
days_for_password_to_expire = int(settings.PASSWORD_EXPIREDAYS) - int(password_changed_from_now.days)
if days_for_password_to_expire < 0:
auth_login(request, user)
request.session['expired'] = True
return redirect('change_password')
Для третьего пункта я реализовал класс промежуточного программного обеспечения, как показано ниже
middleware.py
class AutoRedirect:
def process_request(self, request):
user = request.user
try:
if user:
profile = UserProfile.objects.get(user=user)
if profile.password_changed:
password_changed_from_now = timezone.now() - profile.password_changed
days_for_password_to_expire = int(settings.PASSWORD_EXPIREDAYS) - \
int(password_changed_from_now.days)
if days_for_password_to_expire < 0:
return redirect('change_password')
else:
return redirect('change_password')
except Exception as e:
print e
С вышеупомянутым классом Middleware я получал ошибку как
This webpage has a redirect loop
Терминальный выход
[18/Aug/2015 00:25:15] "GET /change_password/ HTTP/1.1" 302 0
[18/Aug/2015 00:25:15] "GET /change_password/ HTTP/1.1" 302 0
[18/Aug/2015 00:25:15] "GET /change_password/ HTTP/1.1" 302 0
[18/Aug/2015 00:25:15] "GET /change_password/ HTTP/1.1" 302 0
[18/Aug/2015 00:25:15] "GET /change_password/ HTTP/1.1" 302 0
................
................
Я понимаю проблему, с которой он сталкивался, но как я могу избежать этого в логике среднего класса, чтобы проверить, содержит ли пароль пароль, и истекает ли он перенаправление на экран смены пароля? так что пользователь не может получить доступ к любому URL на сайте?
1 ответ
Вы делаете это правильно, но есть еще одна проверка: если пользователь уже находится на экране смены пароля, вы не должны перенаправлять его. Вы можете просто разрешить URL из запроса:
from django.core.urlresolvers import resolve
current_url = resolve(request.path_info).url_name
и сравните, если current_url соответствует 'change_password'.
Также полезно сообщить пользователю, почему он должен сменить свой пароль. Для этого вы можете использовать фреймворк сообщений django.
И в этой строке есть еще одна ошибка:
if days_for_password_to_expire < 0 or not profile.password_changed:
Второе условие всегда будет ложным, потому что вы проверяете это выше.