La validation du formulaire échoue en raison de L'absence de FCRSS

il y a quelques jours, j'ai réinitialisé mon environnement flasque local sans avoir capturé les dépendances via un pip freeze avant que je l'efface. J'ai donc dû réinstaller la dernière version de la pile entière.

à l'improviste, Je ne suis plus en mesure de valider avec des formulaires. Flask prétend que le CSRF aurait disparu.

def register():
    form = RegisterForm()
    if form.validate_on_submit():
       ...
    return make_response("register.html", form=form, error=form.errors)

La première fois que j'envoie un Get je récupère un vide form.errors comme prévu. Maintenant je remplis le formulaire et le soumets et form.errors montre: {'csrf_token': [u'CSRF token missing']}

C'est si étrange. Je me demande si Flask-WTF a changé et je l'utilise à tort.

je peux clairement voir le form.CSRF_token existe, alors pourquoi prétend-il qu'il a disparu?

CSRFTokenField: <input id="csrf_token" name="csrf_token" type="hidden" value="1391278044.35##3f90ec8062a9e91707e70c2edb919f7e8236ddb5">

je n'ai jamais touché le travail de modèle, mais je l'ai poster ici néanmoins:

{% from "_formhelpers.html" import render_field %}
{% extends "base.html" %}
{% block body %}
<div class="center simpleform">
    <h2>Register</h2>
    {% if error %}<p class=error><strong>Error:</strong> {{ error }}{% endif %}
    <form class="form-signin" action="{{ url_for('register') }}" method=post>
        {{form.hidden_tag()}}
        <dl>
            {{ render_field(form.name) }}
            {{ render_field(form.email) }}
            {{ render_field(form.password) }}
            {{ render_field(form.confirm) }}
            <dd><input type=submit value=Register class='btn btn-primary'>
        </dl>
    </form>
</div>
{% endblock %}

est-ce un nouveau bug?

mise à jour:

j'ai tout réinstallé et le problème persiste.

Comme Martijn suggéré, je débogue dans la méthode suivante dans flask_wtf:

def validate_csrf_token(self, field):
        if not self.csrf_enabled:
            return True
        if hasattr(request, 'csrf_valid') and request.csrf_valid:
            # this is validated by CsrfProtect
            return True
        if not validate_csrf(field.data, self.SECRET_KEY, self.TIME_LIMIT):
            raise ValidationError(field.gettext('CSRF token missing'))

la dernière condition est d'augmenter l'erreur de validation.

field.data = "1391296243.8##1b02e325eb0cd0c15436d0384f981f06c06147ec"
self.SECRET_KEY = None (? Is this the problem)
self.TIME_LIMIT = 3600

et vous aviez raison la comparaison HMAC échoue....les deux valeurs sont à chaque fois différents.

return hmac_compare == hmac_csrf

J'ai à la fois SECRET_KEY et CSRF_SESSION_KEY dans ma configuration définie.

16
demandé sur Houman 2014-02-01 21:17:00

4 réponses

l'infrastructure Flask-WTF CSRF rejette un jeton si:

  • le jeton est manquant. Pas le cas ici, vous pouvez voir le jeton dans la forme.

  • il est trop vieux (d'expiration par défaut est définie à 3600 secondes ou une heure). Définissez TIME_LIMIT attribut sur les formulaires pour outrepasser ceci. Sans doute pas le cas ici.

  • si aucun 'csrf_token' clé se trouve dans la session en cours. Vous pouvez apparemment voir le token de la session, donc c'est trop.

  • si la signature HMAC ne correspond pas; la signature est basée sur la valeur aléatoire définie dans la session sous le 'csrf_token' la clé, le secret côté serveur, et l'horodatage d'expiration dans le token.

Avoir éliminé les trois premières possibilités, vous devez vérifier pourquoi la 4ème étape échoue. Vous pouvez déboguer la validation dans flask_wtf/csrf.py fichier,validate_csrf() fonction.

Pour votre installation, vous devez vérifier que la configuration de la session est correcte (surtout si vous n'utilisez pas la configuration par défaut de la session), et que vous utilisez le bon secret côté serveur. La forme elle-même pourrait avoir un SECRET_KEY l'attribut défini, mais n'est pas stable entre les requêtes, ou de l'application WTF_CSRF_SECRET_KEY la touche a changé (cette dernière valeur par défaut est app.secret_key valeur).

le support CSRF a été ajouté dans la version 0.9.0, vérifiez le protection CSRF de la documentation si vous avez amélioré. Le fiole standard-WTF Form classe comprend le jeton CSRF en tant que champ caché, rendre les champs cachés est suffisant pour l'inclure:

{{ form.hidden_tag() }}
15
répondu Martijn Pieters 2015-05-11 21:24:35

j'ai finalement trouvé le problème après presque une journée de travail. :( Un grand merci à Martijn pour son aide.

en fait Le problème réside dans la façon dont la dernière flask_wtf.csrf fonctionne. Les fabricants l'ont complètement remanié.

Vous devez remplacer tous les {{form.hidden_tag()}} dans vos modèles avec les <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>.

et vous devez maintenant activer explicitement la protection CSRF en ajoutant CsrfProtect(app).

documentation est maintenant évidemment reflétant, mais je ne sais pas ce qui a changé et a été la chasse aux fantômes.

C'est un gros problème avec les fonctionnalités obsolètes sans prévenir le développeur d'une façon ou d'une autre. Quiconque met à jour la dernière version, chassera les fantômes comme moi. Mais c'est aussi ma faute si je n'ai pas pris un instantané de mes dépendances. Leçon apprise à la dure.

15
répondu Houman 2014-02-01 22:58:34

pour moi, le problème ne venait pas du fait que Flask-WTF était mal configuré, ou d'un token manquant. Il a été à venir variables d'environnement.

si votre serveur de flasques ne tourne pas sur localhost alors pour que flasque fonctionne correctement, vous devez définir un SERVER_NAME variable d'environnement. Vous avez probablement oublié de modifier le SERVER_NAME valeur quelque part.

Par exemple, vous pourriez avoir quelque chose comme ceci config/settings.py:

SERVER_NAME = 'my-domain.com'

Pour plus d'informations, découvrez ressources

0
répondu louis_guitton 2018-08-07 21:09:58

Au moment de la création de l'application:

from flask_wtf.csrf import CsrfProtect

csrf = CsrfProtect()

app = Flask(__name__)   

...

csrf.init_app(app)

...
0
répondu caverac 2018-08-31 13:46:29