with what tutorial para framework espaƱol djangoproject develop applications python forms flask flask-wtforms

what - framework django para python



La validaciĆ³n del formulario falla debido a que falta CSRF (4)

A la hora de crear la aplicación:

from flask_wtf.csrf import CsrfProtect csrf = CsrfProtect() app = Flask(__name__) ... csrf.init_app(app) ...

Hace unos días, he restablecido el entorno de mi matraz local sin haber capturado las dependencias a través de un pip freeze antes de eliminarlo. Por lo tanto, tuve que volver a instalar la última versión de toda la pila.

Ahora, de la nada, ya no puedo validar con formularios. Flask dice que faltaría CSRF.

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

La primera vez que envío un Get , recupero un form.errors vacío. form.errors como se esperaba. Ahora lleno el formulario y lo presento y se muestra form.errors : {''csrf_token'': [u''CSRF token missing'']}

Esto es tan extraño. Me pregunto si Flask-WTF ha cambiado y lo estoy usando incorrectamente.

Puedo ver claramente el form.CSRF_token existe, entonces ¿por qué dice que faltaba?

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

Nunca toqué la plantilla de trabajo, pero aun así la publico aquí:

{% 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 %}

¿Es este un nuevo error?

ACTUALIZAR:

He reinstalado todo y el problema persiste.

Como sugirió Martijn, estoy depurando en el siguiente método en 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 última condición es elevar el error de validación.

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

Y tenías razón, la comparación HMAC falla ... ambos valores son diferentes cada vez.

return hmac_compare == hmac_csrf

Tengo tanto SECRET_KEY como CSRF_SESSION_KEY en mi configuración definida.


Finalmente encontré el problema después de casi un día de trabajo. :( Muchas gracias a Martijn aunque por su ayuda.

El problema real radica en la forma en que funciona el último flask_wtf.csrf . Los fabricantes lo han revisado por completo.

{{form.hidden_tag()}} reemplazar todos {{form.hidden_tag()}} en sus plantillas con <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> .

Y ahora tiene que habilitar explícitamente la protección CSRF agregando CsrfProtect(app) .

La documentation ahora obviamente refleja eso, pero no sabía que esto había cambiado y estaba persiguiendo fantasmas.

Es un gran problema con la funcionalidad obsoleta sin notificar al desarrollador de alguna manera. Cualquiera que se actualice ahora a la última versión, perseguirá a los fantasmas como lo hice yo. Pero también es mi culpa no haber tomado una instantánea de mis dependencias. Aprendimos la lección de la manera difícil.


La infraestructura CSRF de Flask-WTF rechaza un token si:

  • Falta el token. No es el caso aquí, puede ver el token en el formulario.

  • es demasiado antiguo (la caducidad predeterminada se establece en 3600 segundos, o una hora). Establezca el atributo TIME_LIMIT en los formularios para anular esto. Probablemente no sea el caso aquí.

  • si no se encuentra la clave ''csrf_token'' en la sesión actual. Aparentemente puedes ver el token de sesión, así que eso también está fuera.

  • Si la firma HMAC no coincide; la firma se basa en el valor aleatorio establecido en la sesión bajo la clave ''csrf_token'' , el secreto del lado del servidor y la marca de tiempo de caducidad en el token.

Una vez eliminadas las tres primeras posibilidades, debe verificar por qué falla el cuarto paso. Puede depurar la validación en el archivo flask_wtf/csrf.py , en la función validate_csrf() .

Para su configuración, debe verificar que la configuración de la sesión sea correcta (especialmente si no usa la configuración de sesión predeterminada) y que está utilizando el secreto del lado del servidor correcto. El formulario en sí podría tener un SECRET_KEY atributos SECRET_KEY pero no es estable en todas las solicitudes, o la aplicación WTF_CSRF_SECRET_KEY ha cambiado (la última predeterminada es el valor de app.secret_key ).

La compatibilidad con CSRF se agregó en la versión 0.9.0, consulte la documentación específica de protección de CSRF si actualizó. La clase de Form estándar de Flask-WTF incluye el token CSRF como un campo oculto, renderizar los campos ocultos es suficiente para incluirlo:

{{ form.hidden_tag() }}


Para mí, el problema no se debía a que Flask-WTF estuviera mal configurado o que faltara un token. Venía de las variables de entorno .

Si su servidor Flask no se está ejecutando en localhost, para que Flask funcione correctamente, debe configurar una variable de entorno SERVER_NAME . Es probable que haya olvidado modificar el valor SERVER_NAME algún lugar.

Por ejemplo, podría tener algo como esto en config/settings.py :

SERVER_NAME = ''my-domain.com''

Para más información, echa un vistazo a este gran recurso