flask_wtf.csrf Токены CSRF не совпадают - не удается исправить сообщение об ошибке фляги - PullRequest
0 голосов
/ 06 ноября 2018

Это сообщение, которое я получаю при проверке формы входа в систему:

session: <SecureCookieSession {}>
request.form: ImmutableMultiDict([('eventid', ''), ('csrf_token', 'ImI1N2EwYjFjZmIxZDI4YjQ3ZTIxM2VmNGNkOGQzZTEzYzBiM2U4MzEi.DsNqRA.sw618M5laiwyElfOJ9mAIAAOXig'), ('password', 'admin'), ('username', 'admin'), ('submit', 'Sign In')])
INFO:flask_wtf.csrf:The CSRF tokens do not match.
127.0.0.1 - - [06/Nov/2018 19:18:57] "POST / HTTP/1.1" 200 -
INFO:werkzeug:127.0.0.1 - - [06/Nov/2018 19:18:57] "POST / HTTP/1.1" 200 -

Я печатаю данные формы и session, и кажется, что сессия пуста.

Я понимаю, что сеанс должен иметь токен, но он отсутствует, и я не знаю, что мне нужно сделать, чтобы в сеансе были необходимые данные. Я следовал этому уроку и, похоже, все должно быть установлено автоматически.

Раньше я не использовал flask_wtf, и все работало нормально. Я проверил все доступные вопросы о несоответствии токенов или отсутствующих токенах, но мне не удалось решить мою проблему, используя их предложения.

Вот мои файлы:

__ __ INIT. Ру

#!/usr/bin/env python3

import os

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

from config import Config


app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)

# register blueprints
from app.auth import auth
app.register_blueprint(auth.bp)

Вид: auth.py

from flask import (
    Blueprint,
    flash,
    g,
    redirect,
    render_template,
    request,
    session,
    url_for,
)
from werkzeug.security import check_password_hash, generate_password_hash

from app import db
from app.auth.forms import LoginForm
from app.models import User


bp = Blueprint('auth', __name__)


@bp.route('/', methods=('GET', 'POST'))
@bp.route('/login/', methods=('GET', 'POST'))
def login():
    print('session:', session)
    form = LoginForm()
    print('request.form:', request.form)
    if form.validate_on_submit():
        print('Form is valid')
        eventid = form.eventid.data
        username = form.username.data
        password = form.password.data
        # validate login
        user = User.query.filter_by(username=username.lower()).first()
        error = None
        if not user or not check_password_hash(user.password, password):
            error = 'Incorrect username-password combination.'

        if not error:
            session.clear()
            session['user_id'] = user.id
            return redirect(url_for('performance.index'))

        flash(error)

    return render_template('auth/login.html', title='Sign In', form=form)

Форма: forms.py

from flask_wtf import FlaskForm
from wtforms import (
    BooleanField,
    PasswordField,
    StringField,
    SubmitField,
)
from wtforms.validators import DataRequired


class LoginForm(FlaskForm):
    eventid = StringField('Event ID')
    username = StringField('Username', validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Sign In')

Шаблон: login.html

{% extends 'base.html' %}

{% block header %}
<h3>{% block title %}{{ title }}{% endblock %}</h3>
{% endblock %}

{% block content %}
    <form action="" method="post">
        <div class="form-group">
            <label class="col-sm-12" for="username">
                {{ form.username.label }}
            </label>
            {{ form.username() }}
        </div>
        <div class="form-group">
            <label class="col-sm-12" for="password">
                {{ form.password.label }}
            </label>
            {{ form.password() }}
        </div>
        <div class="form-group">
            <label class="col-sm-12" for="eventid">
                {{ form.eventid.label }}
            </label>
            {{ form.eventid() }}
        </div>
        <div class="form-group">
            {{ form.submit }}
        </div>
        {{ form.hidden_tag() }}
    </form>
{% endblock %}

Конфиг: config.py

import os


class Config:
    instance_path = '/some/path/to/instance/'
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
    DATABASE = os.path.join(instance_path, 'app.sqlite')
    SQLALCHEMY_DATABASE_URI = ('sqlite:///' + os.path.join(instance_path,
                                                           'app.sqlite'))
    SQLALCHEMY_TRACK_MODIFICATIONS = False

Я перепробовал все предложения, я смог найти: - Я установил hidden_tag() в шаблоне; - Я установил SECRETE_KEY в конфиге; - Я пытался перейти с FlaskForms на Forms; - другие решения.

Никто из них не помог. Я сижу с ним уже три вечера. Любое предложение было бы хорошо.

UPDATE

Если я не использую Blueprint, т. Е. Если я использую @app.route(...) вместо @bp.route(...) в моем auth.py, я могу войти в систему, хотя session все еще пуст. Итак, теперь я не понимаю проблемы с планом.

1 Ответ

0 голосов
/ 07 ноября 2018

Я думаю, что вы пропустили эту часть из урока:

Аргумент шаблона form.hidden_tag () создает скрытое поле, содержащее токен, который используется для защиты формы от атак CSRF. Все, что вам нужно сделать, чтобы защитить форму, это включить это скрытое поле и задать переменную SECRET_KEY , определенную в конфигурации Flask. Если вы позаботитесь об этих двух вещах, Flask-WTF сделает все остальное за вас.

Итак, в вашем конфигурационном файле вы должны установить секретный ключ

import os

class Config(object):
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'

Если это не сработает, в вашем login.html попробуйте добавить в начало формы csrf_token примерно так:

<form action="" method="post">
        {{ form.csrf_token }}
        <div class="form-group">
            <label class="col-sm-12" for="username">
                {{ form.username.label }}
     .....
...