'CSRF Token is missing' in Flask but it *is* rendering in the template

元气小坏坏 提交于 2020-06-28 03:41:20

问题


The Problem

When I try to login (using Flask-login) I get Bad Request The CSRF session token is missing but the token is rendering (in the template), secret_key is set, and I'm running locally at localhost:5000.

When I was able to log in, I could no longer use my Flask-WTF forms for the same reason. By calling form.validate() on the route, I got CSRF token missing for all of the forms. Effectively the forms just did nothing. If I look in the template where I call {{form.hidden_tag()}} the CSRF token is as below:

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

The config

My app is initialised via an app factory in __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')

Core module (blueprint)

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)

I don't really know what to try now. The CSRF token is there, but it keeps telling me its missing?

来源:https://stackoverflow.com/questions/59756059/csrf-token-is-missing-in-flask-but-it-is-rendering-in-the-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!