Flask-WTForms 给出错误消息:“CSRF 令牌不匹配。

Flask-WTForms give errors message: "The CSRF tokens do not match."

提问人:Kevinkun 提问时间:1/22/2023 更新时间:1/22/2023 访问量:106

问:

我以为我终于成功了,直到这个错误被显示出来。csrf_token

我的目标是使用 Flask-WTF 验证表单,但使用 Fetch Javascript 处理它(而不是让 validate_on_submit 函数完成这项工作)。因为我想动态地执行它。

如果验证失败,它将显示输入字段和提交按钮之间的错误。如果成功,它将在其他元素 innerHTML 中显示消息。

当我以空输入提交时,它可以工作。它将像我想要的那样显示消息。但是当我输入有效的电子邮件时,它仍然显示错误消息。"Please enter your email address"The CSRF tokens do not match

App.py

import os

from flask import Flask, jsonify, flash, redirect, render_template, request, session
from flask_session import Session
from flask_api import status
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import InputRequired


# Configure flask application
app = Flask(__name__)

# Configure Secret Key
app.config["SECRET_KEY"] = "secret123"

# Create Form Class
class AuthenticationForm(FlaskForm):
    email = StringField('Email Address', [InputRequired(message="Please enter your email address")])


# Ensure templates are auto-reloaded
app.config["TEMPLATES_AUTO_RELOAD"] = True

# Configure session to use filesystem (instead of signed cookies)
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)

# Configure SQLAlchemy databases
basedir = os.path.abspath(os.path.dirname(__file__))

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + os.path.join(basedir, 'newspaper.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

# Create SQLAlchemy object of class
class Readers(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    email = db.Column(db.Text, unique=True, nullable=False)
    hash = db.Column(db.Text, nullable=False)

    def __repr__(self):
        return f'<Readers {self.email}>'


@app.after_request
def after_request(response):
    """Ensure responses aren't cached"""
    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    response.headers["Expires"] = 0
    response.headers["Pragma"] = "no-cache"
    return response


@app.route("/")
def index():
    """Show Newspaper"""
    return redirect('/auth/login')


@app.route("/auth/<authentication>", methods=["GET", "POST"])
def auth(authentication):
    """Log user in"""

    # Forget any user_id
    session.clear()

    # Get form class
    form = AuthenticationForm()
    
    # User reached route via POST (as by submitting a form via POST)
    if request.method == "POST":

        if authentication == 'login':
     
            if form.validate():
                
                data = request.get_json()
                email = data["email"]

                # Check if email already registered in database
                user = Readers.query.filter_by(email=email).first()
                if not user:
                    return "Not Registered Yet", 200
                return "Valid!", 200
  
            return jsonify(form.errors), 400

    # User reached route via GET (as by clicking a link or via redirect)
    return render_template("auth.html", form=form)

auth.html

{% extends "layout.html" %}

{% block title %} 
    Login -  
{% endblock %}

{% block main %} 
    <div class="auth__form-wrapper">
        <div class="auth__title">
            <h2>Log in or create an account</h2>
        </div>
        <div id="success-message"></div>
        <form id="form" method="post">
            {{ form.csrf_token }}
            <fieldset type="email" class="mb-1">
                {{ form.email.label }}
                {{ form.email(autocomplete="off", autofocus=true, required=false) }}
            </fieldset>

            <div id="error-message">
                <span style="color: red;" id="error"></span>
            </div>  

            <button id="continue" class="btn btn-dark">Continue</button>
        </form>
    </div>
    <script src="{{url_for('static', filename='authentication.js')}}"></script>
{% endblock %}

authentication.js(处理表单提交的文件)

const form = document.querySelector('#form');
const successMessage = document.querySelector('#success-message');
const errorMessage = document.querySelector('#error');
const fields = {
    csrf_token: {
        input: document.querySelector('#csrf_token')
    },
    email: {
        input: document.querySelector('#email')
    }
}

form.addEventListener('submit', async (e) => {
    e.preventDefault();
    const response = await fetch('/auth/login', {
        'method': 'POST',
        'headers': {
            'Content-Type': 'application/json'
        },
        'body': JSON.stringify({
            'csrf_token': fields.csrf_token.input.value,
            'email': fields.email.input.value
        })
    });
    if (response.ok) {
        successMessage.innerHTML = await response.text();
    } else {
        const err = await response.json();
        Object.keys(err).forEach((key) => {
            errorMessage.innerHTML = err[key][0];
         });
    }
})

当我使用空输入字段提交时:

empty fields error

当我使用有效的电子邮件提交时:

csrf_token errors

我不明白。我希望你们能帮上忙。我只想创建一个行为类似于《纽约时报》的表单:NYTForm 登录

javascript python html flask csrf-token

评论


答: 暂无答案