错误 使用 CSRF 需要密钥。蟒蛇/烧瓶

时间:2020-12-21 13:08:50

标签: python flask

我收到错误 A secret key is required to use CSRF., 在我的生产环境中,当我在开发环境中时,我的应用程序正常。

该消息很直接,说明了需要什么,但我已经定义了 SECRET_KEY。

def __create_env(env_file: str):
    if not os.path.isfile(env_file):
        context = "FLASK_ENV=production" + "\n"
        context += "ENV=production" + "\n"
        context += "SERVER_NAME=127.0.0.1:8080" + "\n"
        context += "DEBUG=False" + "\n"
        context += "TESTING=False" + "\n"
        context += "PROPAGATE_EXCEPTIONS=False" + "\n"
        context += "SECRET_KEY=my SECRET KEY"+ "\n"
        context += "JWT_SECRET_KEY=....." + "\n"
        with open(env_file, "w") as reader:
            reader.write(context)

我的 __init__.py 看起来像这样:

from flask import (Flask, jsonify, make_response, request)
from flask_jwt_extended import JWTManager
from flask_minify import minify
from flask_wtf import CSRFProtect

from src import (autenticacao, config, util)
from src.views import (vw_estatistica)

app = Flask(__name__)
csrf = CSRFProtect(app)
app.url_map.strict_slashes = False
app.jinja_env.lstrip_blocks = True
app.jinja_env.trim_blocks = True
app.jinja_env.cache = {}
app.config['SESSION_COOKIE_DOMAIN'] = '...com.br'
app.config['SESSION_COOKIE_SECURE'] = True

cache.init_app(app=app, config={
    "CACHE_TYPE": "simple",
    "CACHE_DEFAULT_TIMEOUT": 300
})

minify(app=app, html=True, js=False, cssless=False)

jwt = JWTManager(app)

vw_estatistica.configure(app)

csrf.init_app(app)

我得到的错误是:

<块引用>

回溯(最近一次调用):文件 “/var/www/.../principal/src/views/vw_estatistica.py”,第 25 行,在 loginestistica form = estastica_model.LoginEstatisticaForm() 文件 “/usr/local/lib/python3.8/site-packages/wtforms/form.py”,第 208 行,在 调用返回 type.call(cls​​, *args, **kwargs) 文件 “/usr/local/lib/python3.8/site-packages/flask_wtf/form.py”,第 87 行, 在 init super(FlaskForm, self).init(formdata=formdata, **kwargs) 文件中 “/usr/local/lib/python3.8/site-packages/wtforms/form.py”,第 274 行,在 init self.process(formdata, obj, data=data, **kwargs) 文件 “/usr/local/lib/python3.8/site-packages/wtforms/form.py”,第 131 行,在 流程 field.process(formdata) 文件 “/usr/local/lib/python3.8/site-packages/wtforms/csrf/core.py”,行 43、进程中self.current_token = self.csrf_impl.generate_csrf_token(self) 文件 “/usr/local/lib/python3.8/site-packages/flask_wtf/csrf.py”,第 139 行, 在 generate_csrf_token 中返回 generate_csrf( File “/usr/local/lib/python3.8/site-packages/flask_wtf/csrf.py”,第 33 行, 在 generate_csrf secret_key = _get_config( 文件 “/usr/local/lib/python3.8/site-packages/flask_wtf/csrf.py”,第 128 行, 在 _get_config 中引发 RuntimeError(message) RuntimeError: A secret key 需要使用 CSRF。

vw_estatistica.py》,第25行,loginestatistica form = estatistica_model.LoginEstatisticaForm()如下。

import json
import traceback

import flask
from flask import Blueprint, jsonify, render_template, redirect, abort, url_for, flash, request
from flask_restful import Api, Resource

from datetime import timedelta, datetime

from src import util, config
from src.models import (log_model, estatistica_model, menu_model)

mod: Blueprint = Blueprint('vw_estatisitca', __name__, template_folder='templates', static_folder='static')


def configure(app):
    api = Api(mod)
    api.add_resource(ObterTopoEstatistica, '/obterTopoEstatistica', '/obterTopoEstatistica/<string:pagina>')
    app.register_blueprint(mod)


@mod.route("/estatistica/login", methods=["GET", "POST"])
def loginestatistica():
    try:
        form = estatistica_model.LoginEstatisticaForm() # line 25

        if request.method == 'POST' and form.validate():
            senha_cript = util.encrypt(form.password.data, config.CHAVE_CRIPTOGRAFIA)

            usuario_estatistica = estatistica_model.get_usuario_estatistica(form.login.data, senha_cript)

            if usuario_estatistica is not None:
                response = flask.make_response(redirect('https://estatistica....com.br'))
                data_expiracao = (datetime.now() + timedelta(days=1))
                id_usuario = util.encrypt(str(usuario_estatistica.id), config.CHAVE_CRIPTOGRAFIA)

                json_usuario_estatistica = json.dumps({'IdUsuario': id_usuario,
                                                       'NomeUsuario': usuario_estatistica.Usuario,
                                                       'DataUltimoAcesso': usuario_estatistica.UltimoAcesso}
                                                      , indent=4, sort_keys=True, default=str)

                response.set_cookie(value=json_usuario_estatistica,
                                    key='estatistica',
                                    max_age=None,
                                    expires=data_expiracao,
                                    path='/',
                                    domain='....com.br',
                                    secure=True,
                                    httponly=False,
                                    samesite='Lax')

                return response

            else:
                flash("Credênciais incorretas", "danger")
                return redirect(url_for(".loginestatistica"))

        menus: list = menu_model.get_menu(request.host_url)
        return render_template("login-estatistica.html",
                               form=form,
                               menus=menus
                               )

    except Exception as error:
        log_model.Salvar('Site www', 'vw_estatistica.py', f'{traceback.format_exc()}', 'estatistica',
                         log_model.Severidade.High)
        abort(502, description=error)
    finally:
        pass

我的 HTML 页面是这样的。

{% extends "layout.html" %}

{%- block dataLayer -%}
{{ dataLayer | safe }}
{%- endblock -%}


{% block content %}
<div class="container-fluid">
    <br />
    <form  action=" {{url_for('.loginestatistica')}}" method="POST">
        {{ form.csrf_token }}
        <div class="row justify-content-center">
            <div class="col-md-4">
                <div class="modal-content">
                    <div class="modal-header text-center">
                        <h1 class=" text-primary text-block h2 font-weight-bold mb-0">Kalunga - Estatística</h1>
                    </div>
                    <div class="modal-body">
                        <div class="input-group mb-3">
                            <div class="input-group-prepend">
                                <span class="input-group-text font-weight-bold"><i
                                        class="fas fa-user mr-1"></i>Login</span>
                            </div>
                            {{ form.login(class_="form-control") }}
                        </div>
                        <div class="input-group mb-3">
                            <div class="input-group-prepend">
                                <span class="input-group-text font-weight-bold"><i
                                        class="fas fa-key mr-1"></i>Senha</span>
                            </div>
                            {{ form.password(class_="form-control") }}
                        </div>
                        <div class="input-group mb-12">
                            <div class="col-md-4">
                                <button type="submit" class="btn btn-primary btn-lg">Login</button>
                            </div>
                            <div class="col-md-6 text-center">
                                <a href="{{url_for('.recuperaracessoestatistica')}}">Recupera acesso</a>
                            </div>
                        </div>
                        <div class="input-group mb-12">
                            {% include 'partials/notification.html' %}
                            {% include 'partials/form-erros.html' %}
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </form>
</div>
<br />
{% endblock %}

我已经看到一些与此类错误相关的问题,但我找不到问题,我也尝试按照 documentation 中的步骤操作,但没有奏效。

1 个答案:

答案 0 :(得分:2)

定义 secret_key 之类的

app = Flask(__name__)
app.secret_key = settings.SECRET_KEY

app.config['SECRET_KEY'] = settings.SECRET_KEY

在此处查找详细信息https://flask.palletsprojects.com/en/1.1.x/config

您应该按照此处的指定手动加载 Flask 应用程序的环境 https://flask.palletsprojects.com/en/1.1.x/api/#configuration