'CSRF Token отсутствует' в Flask, но * это * рендеринг в шаблоне - PullRequest
1 голос
/ 15 января 2020

Проблема

Когда я пытаюсь войти (используя Flask -login), я получаю Bad Request The CSRF session token is missing, но токен рендерится (в шаблоне), секретный ключ установлен, и я работаю локально на localhost:5000.

Когда я смог войти в систему, я больше не мог использовать свои формы Flask -WTF по той же причине. Позвонив по маршруту form.validate(), я получил CSRF token missing для всех форм. Фактически формы просто ничего не сделали. Если я посмотрю в шаблоне, где я вызываю {{form.hidden_tag()}}, токен CSRF будет выглядеть следующим образом:

<input id="csrf_token" name="csrf_token" type="hidden" value="sdfksdognslkdgnskldgjsd.Xh897A.i_changed_this_just_in_case">

Конфигурация

Мое приложение инициализируется через фабрику приложений в __init.py__

def create_app(config=BaseConfig):
    # Initialise the Flask app
    app = Flask(__name__)
    app.config.from_object(config)
    initialise_extensions(app)
    register_template_filters(app)
    app.register_blueprint(core)
    register_shell_context(app)

    return app

def initialise_extensions(app):
    # Since the application instance is now created, pass it to each Flask
    # extension instance to bind it to the Flask application instance (app)
    db.init_app(app)
    migrate.init_app(app, db)
    csrf.init_app(app)
    # Login
    login.init_app(app)
    login.login_view = 'core.login'

class BaseConfig(object):
    SECRET_KEY = os.environ.get('SECRET_KEY')
    FLASK_DEBUG = os.environ.get('FLASK_DEBUG')
    DB_NAME = os.environ.get('DB_NAME')
    DB_USER = os.environ.get('DB_USER')
    DB_PASS = os.environ.get('DB_PASS')
    DB_SERVICE = os.environ.get('DB_SERVICE')
    DB_PORT = os.environ.get('DB_PORT')
    SQLALCHEMY_DATABASE_URI = 'postgresql://{0}:{1}@{2}:{3}/{4}'.format(
        DB_USER, DB_PASS, DB_SERVICE, DB_PORT, DB_NAME
    )
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    BOT_TOKEN = ''
    WTF_CSRF_ENABLED = True
    SESSION_COOKIE_SECURE = True
    # WTF_CSRF_SECRET_KEY = 'secret #This makes no difference regardless if its set or not.

Extensions.py

import os
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate
from flask_login import LoginManager
from cryptography.fernet import Fernet
import redis
from flask_sqlalchemy import SQLAlchemy
from flask_wtf.csrf import CSRFProtect

# Initialise basics
db = SQLAlchemy()

# Sort Migrate out
migrate = Migrate(compare_type=True)

# Initialise Marshmallow
ma = Marshmallow()

# Get cryptography
en = Fernet(os.getenv('ENV').encode())

# CSRF protect
csrf = CSRFProtect()

# use Flask-Login extension for login forms
login = LoginManager()
login.login_view = 'login'

# Initialise redis
redis_host = os.getenv('REDIS_DB')
rdb = redis.Redis(host=redis_host, port='6379')

Основной модуль (чертеж)

from flask import Blueprint

core = Blueprint('core', __name__, template_folder='templates')

from . import views

core.views

@core.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('core.index'))
    form = LoginForm()
    print('------ {0}'.format(form.csrf_token))
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user is None or not user.check_password(form.password.data):
            flash('Incorrect Username or Password')
            return redirect(url_for('core.login'))
        login_user(user, remember=form.remember_me.data)
        next_page = request.args.get('next')
        if not next_page or url_parse(next_page).netloc != '':
            next_page = url_for('core.index')
        return redirect(next_page)
    return render_template('login.html', title='Sign In', form=form)

Я действительно не знаю, что попробовать сейчас. Токен CSRF есть, но он постоянно сообщает мне, что его пропали?

...