重置密码中链接无效。

3

我想在Django中编写自定义用户,但是重置密码时出现了问题。我在urls.py中使用以下URL:

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/

当我点击它时,出现了以下信息,显示这是一个无效的链接:The password reset link was invalid, possibly because it has already been used. Please request a new password reset

我已经搜索了很多但没有找到解决方法。请问有人能帮助我吗?非常感谢。


请帮帮我... - parimah ziayi
有人可以帮我吗? - parimah ziayi
你们有像SendGrid这样的电子邮件服务吗?我遇到了同样的问题,我注意到链接是由SendGrid处理/由Mail预览(因此使其无效)。 - John Pang
1个回答

2
如果您使用 CSRF_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True,则您的网址必须在 https 中。
您有两个选项。 重写 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 %}

选项二: 您必须确保您的服务器在https上运行,模板电子邮件搜索请求.schema如果是http或https并填写所使用的模式。我将我的nginx服务器设置为代理,但我的django服务器仍在http上运行,因此我的电子邮件模板仅生成了http。

最初的回答:

请确保您的服务器在https上运行,并且模板电子邮件搜索请求.schema是否为http或https并填写所使用的模式。如果您的django服务器仍在http上运行,则可能会导致您的电子邮件模板仅生成http。作为解决方案,您可以将您的django服务器设置为https。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接