首页 > 解决方案 > 使用 CLI 命令生成 Flask 密钥

问题描述

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

Flask 文档说可以在没有应用程序上下文的情况下运行命令,但似乎仍然创建了该应用程序,即使该命令无权访问它。如何在不阻止 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

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

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

标签: pythonflaskconfiguration

解决方案


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

import os

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

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

AFAIK 密钥不一定是永久的,它应该在 Flask的整个生命周期内保持稳定,因为它将用于会话 cookie 和可能的一些内部内容,但据我所知,这并不重要。

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

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

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

所以我认为单独处理部署是有意义的,无论是使用 bash 脚本还是 Ansible,您还可以收紧权限并自动化其他事情。


推荐阅读