问题
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