Задать вопрос
@Ivan-Proger
Начинающий Python/Django разработчик.

Как решить проблему с csrf_token?

Есть страница А на которой пользователь указывает свою почту для смены пароля. На почту приходить сообщение со ссилкой на страницу В. На странице В обновляет свой пароль и его переводит на страницу пользователя с помощью redirect.
Когда пользователь переходит на вкладку со страницой А, с которой было отравлено сообщение на почту и обновляет ее, отправляя форму повторно, происходит ошибка "Forbidden (403)
CSRF verification failed. Request aborted."
Как можно обновить csrf? или как можно обновить саму страницу А после авторизации? или есть другой способ исправить эту проблему?

Settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                # 'django.template.context_processors',
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'Performer.context_processors.context_processor',
            ],
        },
    },
]


View.py - страница А с которой пользователь отравляет сообщение на свою почту.
class ForgotPassword(View):
    def get(self, request):

        form = EmailForm()

        return render(request, 'Performer/Forgot_password.html', context={'form': form})

    def post(self, request):

        form = EmailForm(request.POST)

        if request.method == 'POST' and form.is_valid():
            email = request.POST.get('email')
            try:
                user = User.objects.get(email=email)
            except ObjectDoesNotExist:
                message = 'Неверный Email'
                return render(request, 'Performer/Forgot_password.html', context={'form': form, 'message': message})

            signer = Signer()

            global script_email

            script_email = signer.sign(email)

            link = 'http://127.0.0.1:8000/change_password/' + script_email.split(':')[1] + '/'

            subject = 'Изменение пароля'

            html_message = render_to_string(
                'Performer/Password_message.html', {'link': link}
            )

            send_mail(subject, 'message', settings.EMAIL_HOST_USER, [email], html_message=html_message, fail_silently=False)

            message = 'Сообщение отправлено'

            return render(request, 'Performer/Forgot_password.html', context={'form': form, 'message': message})


Forgot_pass.html - Страница А с которой пользователь отравляет сообщение на свою почту.
{% extends 'base.html' %}

{% block content %}
    <div class="forgot-pass-wrapper">
        <div class="forgot-pass-content">
            {% if message %}
                <div class="alert alert-info">{{ message }}</div>
            {% else %}
                <form class="forgot-pass-form" method="POST">{% csrf_token %}
                    
                    {{ form.as_p }}

                    <button class="btn btn-primary">Изменить пароль</button>
                </form>
            {% endif %}
        </div>
    </div>
{% endblock %}


View.py - Страница В на которой пользователь меняет свой пароль.
class ChangePassword(View):
    def get(self, request, link):

        signer = Signer()

        global email

        email = signer.unsign(script_email)

        audit = signer.sign(email).split(':')[1]

        if link != audit:
            message = 'Паге нот фаунд'

            form = EmailForm()

            return render(request, 'Performer/Forgot_password.html', context={'form': form, 'message': message})

        form = ChangePasswordForm()

        return render(request, 'Performer/Change_password.html', context={'form': form})

    def post(self, request, link):

        form = ChangePasswordForm(request.POST)

        if request.method == 'POST' and form.is_valid():

            user = User.objects.get(email=email)

            new_password = form.cleaned_data['password_2']

            user.set_password(new_password)

            user.save()

            user = authenticate(request, username=user.username, password=new_password)

            login(request, user)

            return redirect('/user_profile/')


Change_password.html - Страница В
{% extends 'base.html' %}

{% block content %}
    <div class="forgot-pass-wrapper">
        <div class="forgot-pass-content">
            <form class="change-pass-form" method="POST">{% csrf_token %}

                {{ form.as_p }}

                <button class="btn btn-primary">Изменить пароль</button>
            </form>
        </div>
        
    </div>
{% endblock %}
  • Вопрос задан
  • 1852 просмотра
Подписаться 1 Средний 2 комментария
Решения вопроса 2
Guest007
@Guest007
Django, Python, Linux и всё такое...
Если страница А это форма с запросом на сброс (смену) пароля через емайл, то зачем возвращаться на эту страницу после установки нового пароля? Это нелогично.
А так - не вижу проблемы. На крайний случай - перегрузи (обнови) страницу (по F5 или снова открыв её по URLу) чтобы она снова по GET отдалась.
Ответ написан
tema_sun
@tema_sun
На странице А добавьте редирект после успешной отправки формы, тогда по f5 форма не будет отправляться снова.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы