python - 使用 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
我考虑过的一些替代方案:
我可以允许在没有密钥的情况下运行应用程序,因此该命令可以正常工作,但我不想让在没有密钥的情况下意外运行实际的 Web 服务器成为可能。当有人尝试使用具有 cookie 的路由时,这将导致错误 500,并且在启动服务器时可能并不明显。
该应用程序可以按照此处的建议在第一个请求到来之前检查配置,但是这种方法不会比以前的选项好多少,以便于设置。
也建议使用Flask-Script,但 Flask-Script 本身表示不再维护,并指向 Flask 的内置 CLI 工具。
如果缺少配置,我可以在终止应用程序之前使用短暂的延迟,因此 CLI 命令将能够运行,但在尝试运行服务器时很容易注意到丢失的密钥。不过,这将是一种相当受诅咒的方法,谁知道甚至可能是非法的。
我错过了什么吗?这是 Flask 中的错误还是我应该为自动生成密钥做一些完全不同的事情?这是在滥用 Flask CLI 系统的理念吗?首先生成环境文件是不好的做法吗?
解决方案
我认为你让它变得比它应该的更复杂。考虑以下代码:
import os
app.config['SECRET_KEY'] = os.urandom(24)
应该足够了。(但我更喜欢为 Flask 使用配置文件)。
AFAIK 密钥不一定是永久的,它应该在 Flask的整个生命周期内保持稳定,因为它将用于会话 cookie 和可能的一些内部内容,但据我所知,这并不重要。
如果您的应用程序被中断,用户将失去他们的会话,但没什么大不了的。
这取决于您当前的部署实践,但如果您使用 Ansible,例如,您可以自动创建配置文件和/或环境变量,并在启动服务之前进行一些健全性检查。
您的方法的问题是,据我了解,您必须授予 Web 服务器权限才能写入应用程序目录,这对于安全 POV 来说并不是最佳的。Web 用户不应有权修改应用程序文件。
所以我认为单独处理部署是有意义的,无论是使用 bash 脚本还是 Ansible,您还可以收紧权限并自动化其他事情。
推荐阅读
- javascript - onClick 不起作用
- javascript - 如何使用 react 与 asp.net MVC 创建模块化站点/门户
- apache - 在 WAMP 中使用 LDAP 的反向代理身份验证失败
- python - Web Scraping BeautifulSoup- CoinMarketCap.com 历史数据(查找最新日期)
- css - 如何解决边缘浏览器中的表格布局固定问题?
- javascript - 如何从源数组生成随机数组而不重复索引?
- amazon-web-services - 在 AWS Lambda 包中存储机密
- ruby - ruby server.rb 在终端上不起作用
- regex - 在原子编辑器中使用正则表达式进行条件替换
- angular - 无法在角度/打字稿中为对象中的键赋值