django - reset_password 中的无效链接

标签 django

我想在 Django 中编写一个自定义用户,但我对重置密码有疑问。我将下面的 URL 用于 urls.py

url(r'^reset_password_confirm/(?P<uidb64>[0-9A-Za-z_\-\']+)-(?P<token>[0-9A-Za-z\-\']+)/$', PasswordResetConfirmView.as_view() , name='reset_password_confirm'),
url(r'^reset_password', ResetPasswordRequestView.as_view())

这是我对重设密码并确认的看法

class ResetPasswordRequestView(FormView):
        # User = get_user_model()
        template_name = "test_template.html"    #code for template is given below the view's code
        success_url = 'reset_password'
        form_class = PasswordResetRequestForm

        @staticmethod
        def validate_email_address(email):
            try:
                validate_email(email)
                return True
            except ValidationError:
                return False

        def post(self, request, *args, **kwargs):
            form = self.form_class(request.POST)
            if form.is_valid():
                data= form.cleaned_data["email_or_username"]
            if self.validate_email_address(data) is True:                 #uses the method written above
                '''
                If the input is an valid email address, then the following code will lookup for users associated with that email address. If found then an email will be sent to the address, else an error message will be printed on the screen.
                '''
                associated_users= User.objects.filter(Q(email=data)|Q(username=data))
                if associated_users.exists():
                    for user in associated_users:
                            c = {
                                'email': user.email,
                                'domain': request.META['HTTP_HOST'],
                                'site_name': 'your site',
                                'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                                'user': user,
                                'token': default_token_generator.make_token(user),
                                'protocol': 'http',
                                    }
                            subject_template_name='password_reset_subject.txt' 
                            # copied from django/contrib/admin/templates/registration/password_reset_subject.txt to templates directory
                            email_template_name='password_reset_email.html'    
                            # copied from django/contrib/admin/templates/registration/password_reset_email.html to templates directory
                            subject = loader.render_to_string(subject_template_name, c)
                            # Email subject *must not* contain newlines
                            subject = ''.join(subject.splitlines())
                            email = loader.render_to_string(email_template_name, c)
                            send_mail(subject, email, DEFAULT_FROM_EMAIL , [user.email], fail_silently=False)
                    result = self.form_valid(form)
                    messages.success(request, 'An email has been sent to ' + data +". Please check its inbox to continue reseting password.")
                    return result
                result = self.form_invalid(form)
                messages.error(request, 'No user is associated with this email address')
                return result
            else:
                '''
                If the input is an username, then the following code will lookup for users associated with that user. If found then an email will be sent to the user's address, else an error message will be printed on the screen.
                '''
                associated_users= User.objects.filter(username=data)
                if associated_users.exists():
                    for user in associated_users:
                        c = {
                            'email': user.email,
                            'domain': 'example.com', #or your domain
                            'site_name': 'example',
                            'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                            'user': user,
                            'token': default_token_generator.make_token(user),
                            'protocol': 'http',
                            }
                        subject_template_name='password_reset_subject.txt'
                        email_template_name='password_reset_email.html'
                        subject = loader.render_to_string(subject_template_name, c)
                        # Email subject *must not* contain newlines
                        subject = ''.join(subject.splitlines())
                        email = loader.render_to_string(email_template_name, c)
                        send_mail(subject, email, DEFAULT_FROM_EMAIL , [user.email], fail_silently=False)
                    result = self.form_valid(form)
                    messages.success(request, 'Email has been sent to ' + data +"'s email address. Please check its inbox to continue reseting password.")
                    return result
                result = self.form_invalid(form)
                messages.error(request, 'This username does not exist in the system.')
                return result
            messages.error(request, 'Invalid Input')
            return self.form_invalid(form)  

class PasswordResetConfirmView(FormView):
    template_name = "password_reset_confirm.html"
    success_url = 'admin'
    form_class = SetPasswordForm

    def post(self, request, uidb64=None, token=None, *arg, **kwargs):
        """
        View that checks the hash in a password reset link and presents a
        form for entering a new password.
        """
        UserModel = get_user_model()
        form = self.form_class(request.POST)
        assert uidb64 is not None and token is not None  # checked by URLconf
        try:
            uid = urlsafe_base64_decode(uidb64)
            user = UserModel._default_manager.get(pk=uid)
        except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
            user = None

        if user is not None and default_token_generator.check_token(user, token):
            if form.is_valid():
                new_password= form.cleaned_data['new_password2']
                user.set_password(new_password)
                user.save()
                messages.success(request, 'Password has been reset.')
                return self.form_valid(form)
            else:
                messages.error(request, 'Password reset has not been unsuccessful.')
                return self.form_invalid(form)
        else:
            messages.error(request,'The reset password link is no longer valid.')
            return self.form_invalid(form) 

它发送一封包含无效链接的电子邮件,例如 HTTP://127.0.0.1:8000/reset_password_confirm/b'MjM'-4y1-68809e63d52242805bd7/

当我点击它时,我收到了一条消息,显示它是无效的 密码重置链接无效,可能是因为它已被使用。请请求重设新密码

我搜索了很多,没有任何解决方案。有人可以帮我吗? 非常感谢

最佳答案

如果您使用 CSRF_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True 您的网址必须为 https。

您有 2 个选择。 重写reset.html模板,在rootproject\templates\registration\password_reset_email.html

中创建一个文件

可以强制https的内容,模板为:

{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this email because you 
requested a password reset for your user account at
{{ site_name }}.{% endblocktrans %}

{% trans "Please go to the following page and choose a 
new password:" %}
{% block reset_link %}
https://{{ domain }}{% url 'password_reset_confirm' 
uidb64=uid token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} 
{{ user.get_username }}

{% trans "Thanks for using our site!" %}

{% blocktrans %}The {{ site_name }} team{% endblocktrans %}

{% endautoescape %}

选项 2: 您必须确保您的服务器在 https 上运行,模板电子邮件搜索 request.schema 如果是 http 或 https 并且填充了使用的模式。我的 nginx 服务器通过 https 作为代理,但我的 django 服务器在 http 上运行,因此我的电子邮件模板仅使用 http 生成。

关于django - reset_password 中的无效链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51441993/

相关文章:

python - 如何从装饰器向基于 Django 类的 View 添加/修改属性?

Django admin - 如何使 "inlines"可折叠?

python - listOfArticles() 只接受 1 个参数(给定 2 个参数)

Django似乎以UTC格式显示日期时间

django - 一个 BeautifulSoup 文档可以使用多个过滤器吗?

Django 自定义用户密码未进行哈希处理

python - 如何将缓存文件图像添加到 Django HttpResponse

Django 1.3.1 Heroku Postgres 错误

python - 在自定义用户的配置文件中发现不需要的随机值

python - Django 将单独的变量序列化为 json