【问题标题】:Generate Flask secret key with a CLI command使用 CLI 命令生成 Flask 密钥
【发布时间】:2021-10-07 02:46:46
【问题描述】:

我想通过提供custom CLI command 自动生成SECRET_KEY 并将其保存到.env 来使我的Flask 应用程序的设置尽可能简单。但是,调用命令似乎会创建 Flask 应用程序的一个实例,然后它需要尚未存在的配置。

Flask 文档说run commands without application context 是可能的,但似乎仍然创建了该应用程序,即使该命令无权访问它。 如何在不阻止 CLI 命令的情况下阻止 Web 服务器运行?

这是几乎可以工作的代码。请注意,它需要python-dotenv 包,并且使用flask run 而不是python3 app.py 运行。

import os
import secrets
from flask import Flask, session

app = Flask(__name__)

@app.cli.command(with_appcontext=False)
def create_dotenv():
    cwd = os.getcwd()
    filename = '.env'
    env_path = os.path.join(cwd, filename)

    if os.path.isfile(env_path):
        print('{} exists, doing nothing.'.format(env_path))
        return

    with open(env_path, 'w') as f:
        secret_key = secrets.token_urlsafe()
        f.write('SECRET_KEY={}\n'.format(secret_key))

@app.route('/')
def index():
    counter = session.get('counter', 0)
    counter += 1
    session['counter'] = counter
    return 'You have visited this site {} time(s).'.format(counter)

# putting these under if __name__ == '__main__' doesn't work
# because then they are not executed during `flask run`.

secret_key = os.environ.get('SECRET_KEY')

if not secret_key:
    raise RuntimeError('No secret key')

app.config['SECRET_KEY'] = secret_key

我考虑过的一些替代方案:

  • 我可以允许在没有密钥的情况下运行应用程序,因此该命令可以正常工作,但我不想让在没有密钥的情况下意外运行实际的 Web 服务器成为可能。当有人尝试使用具有 cookie 的路由时,这将导致错误 500,并且在启动服务器时可能并不明显。

  • 应用程序可以按照here 的建议在第一个请求到来之前检查配置,但这种方法不会比以前的选项好多少,以便于设置。

  • Flask-Script 也是 suggested,但 Flask-Script 本身说 it's no longer mainained 并指向 Flask 的内置 CLI 工具。

  • 如果缺少配置,我可以在终止应用程序之前使用短暂的延迟,这样 CLI 命令将能够运行,但在尝试运行服务器时很容易注意到丢失的密钥。不过,这将是一种相当受诅咒的方法,谁知道甚至可能是非法的。

我错过了什么吗?这是 Flask 中的一个错误,还是我应该为自动生成密钥做一些完全不同的事情?这是在滥用 Flask CLI 系统的理念吗?首先生成环境文件是不好的做法吗?

【问题讨论】:

    标签: python flask configuration


    【解决方案1】:

    我认为你让它变得比它应该的更复杂。 考虑以下代码:

    import os
    
    app.config['SECRET_KEY'] = os.urandom(24)
    

    应该够了。 (但我更喜欢使用 Flask 的配置文件)。

    AFAIK 密钥不必是永久的,它应该在 Flask 的生命周期内保持稳定,因为它将被使用用于会话 cookie,可能还有一些内部的东西,但据我所知没有什么重要的。

    如果您的应用被中断,用户会失去他们的会话,但没什么大不了的。

    这取决于您当前的部署实践,但如果您使用 Ansible,例如,您可以自动创建配置文件和/或环境变量,并在启动服务之前进行一些健全性检查。

    您的方法的问题在于,据我了解,您必须授予 Web 服务器 权限 才能写入应用程序目录,这对于安全 POV 来说并不是最佳的。网络用户不应有权修改应用程序文件。

    所以我认为使用 bash 脚本或 Ansible单独进行部署是有意义的,您还可以收紧权限并自动化其他工作。

    【讨论】:

      【解决方案2】:

      作为一种解决方法,您可以使用单独的 Python/shell 脚本文件来生成 SECRET_KEY.env 的其余部分。

      这可能是唯一需要能够在没有配置的情况下运行的脚本,因此您的存储库不应该因为这样做而变得过于混乱。只需在 README 中提及脚本,它可能也不会导致明显不同的设置体验。

      【讨论】:

        【解决方案3】:

        我同意先例的答案,无论如何你可以写类似的东西

        secret_key = os.environ.get('SECRET_KEY') or secrets.token_urlsafe(32)
        

        这样您仍然可以使用环境中配置的 SECRET_KEY 变量。如果出于某种原因,python 没有找到变量,它将由“或”之后的部分生成。

        【讨论】:

          猜你喜欢
          • 2014-02-13
          • 2011-05-16
          • 1970-01-01
          • 2021-01-20
          • 1970-01-01
          • 2018-01-21
          • 2021-10-01
          • 2016-12-24
          • 1970-01-01
          相关资源
          最近更新 更多