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:

Второе условие всегда будет ложным, потому что вы проверяете это выше.

Другие вопросы по тегам