@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 %}
  • Вопрос задан
  • 1839 просмотров
Решения вопроса 2
Guest007
@Guest007
Django, Python, Linux и всё такое...
Если страница А это форма с запросом на сброс (смену) пароля через емайл, то зачем возвращаться на эту страницу после установки нового пароля? Это нелогично.
А так - не вижу проблемы. На крайний случай - перегрузи (обнови) страницу (по F5 или снова открыв её по URLу) чтобы она снова по GET отдалась.
Ответ написан
tema_sun
@tema_sun
На странице А добавьте редирект после успешной отправки формы, тогда по f5 форма не будет отправляться снова.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы