Web插件管理¶
在v3.3.0,恢复并增强了以前旧版本的blueprint,新增了插件安装功能。
您可以在您的Web应用程序中注册blueprint,并设置蓝图前缀,步骤大概如下:
from flask import Flask
from flask_pluginkit import PluginManager, blueprint
app = Flask(__name__)
PluginManager.init_app(app)
app.register_blueprint(blueprint, url_prefix='/pluginmanager')
启动应用,访问/pluginmanager页面,以我们的 example-fulldemo 为例,效果图是:
这个页面支持中英双语,下面是中文的页面效果:
使用说明¶
这个蓝图只有一个页面,这个页面包含三个主要功能:
禁用、启用插件
重载应用
禁用、启用插件都需要重载应用程序才会生效,为了安全,重载应用程序有一些限制。
只能在使用Gunicorn或uWSGI后台启动的正式环境中有效,而且要求应用程序的配置项中的 ENV 的值是 production ,另外还需要您手动安装psutil模块,例如:
pip install psutil
。如果您使用Gunicorn,需要应用程序的配置项中 PLUGINKIT_GUNICORN_ENABLED 的值为True,并且 PLUGINKIT_PROCESSNAME 的值为具体的程序进程名。
备注
Gunicorn后台启动一般是master-worker模式,这里要求的 PLUGINKIT_PROCESSNAME 是master进程名,不包含 gunicorn: master [] ,是 [] 里的进程名,没有默认值。
如果您使用uWSGI,需要应用程序配置项 PLUGINKIT_UWSGI_ENABLED 的值为True, PLUGINKIT_PROCESSNAME 默认是uwsgi,一般可以不用修改。
上诉情况满足后才能正常重载应用,以下是示例:
$ pip install psutil $ cat app.py from flask_pluginkit import Flask, blueprint, PluginManager app = Flask(__name__) app.config.update( ENV='production', PLUGINKIT_GUNICORN_ENABLED=True, PLUGINKIT_PROCESSNAME="app:app" ) pm = PluginManager(app) app.register_blueprint(blueprint, url_prefix='/pluginmanager') $ gunicorn -b 127.0.0.1:5000 app:app --daemon $ ps aux | grep -v grep | grep gunicorn root master-pid ...... gunicorn: master [app:app] root worker-pid ...... gunicorn: worker [app:app]
小技巧
Flask v1.0 新增了ENV配置,默认值是production。
安装插件
前两个操作很简单,第三个功能需要详细说明下。
安装插件有三种情况:
上传本地插件
这个操作会上传一个压缩文件到您的服务器的临时目录中,然后解压到web应用程序的插件目录(由
__init__()
控制),重复上传一个压缩包会覆盖已经解压的文件。
下载远程插件
类似于上面一种情况,只不过不是上传本地的压缩文件了,而是下载远程的压缩文件到您的服务器的临时目录中,后续步骤跟上面一样。
这里的远程url要求很严格,它必须是一个有效的压缩文件下载地址,且能解析出有效的文件名(即文件后缀是.tar.gz、.tgz或.zip)。值得一提的是,Flask-PluginKit提供了四种方法自动获取远程url的文件名,基本能满足要求(数字表示优先级):
url添加 plugin_filename 查询参数
直接从url中解析出文件名
解析返回头 Content-Disposition
解析返回头 Content-Type
输入框中有效的url示例:
for 1, http://xx.com/download?plugin_filename=xx.zip for 2, http://xx.xx.com/plugin-v0.0.1.tar.gz for 3 and 4, https://codeload.github.com/saintic/flask-pluginkit-demo/zip/master
安装模块
这种情况是新增的,它是依靠pip模块的接口直接安装远程压缩包,可以是pypi的包,也可以是VCS的项目URL,直接安装到python全局环境中,您需要手动通过
plugin_packages
调用。输入框参数示例:
flask-pluginkit-valine git+https://github.com/saintic/flask-pluginkit-demo@master
备注
由于安装模块需要时间,所以这种情况会开启线程处理,安装成功后交给一个消息队列,页面中会每隔5秒查询下消息并显示。
认证¶
Web管理页面对于管理员来说其实是危险的,如果其他人随意访问,那么可能会对系统造成危害,因此,访问这个蓝图前,运行了一个钩子函数以验证访问者。
验证访问者目前支持四种主要方法和一种辅助方法,前者通过应用程序配置项 PLUGINKIT_AUTH_METHOD
定义,后者通过 PLUGINKIT_AUTH_AID_METHOD
定义。
PLUGINKIT_AUTH_METHOD ,支持四种类型的值。
BOOL
这种方法会通过
flask.g
获取配置里 PLUGINKIT_AUTH_BOOLFIELD 字段的值(默认值是signin),为True时,通过验证。示例:
from flask import Flask, g from flask_pluginkit import blueprint, PluginManager app = Flask(__name__) pm = PluginManager(app) app.config.update( PLUGINKIT_AUTH_METHOD="BOOL", PLUGINKIT_AUTH_BOOLFIELD="auth" ) app.register_blueprint(blueprint, url_prefix='/pluginmanager') @app.before_request def br(): g.auth = True
BASIC
HTTP Basic Auth,简单但不安全的方法,这种方法要求有username和password,所以要求应用程序配置项 PLUGINKIT_AUTH_USERS ,是一个dict,key是username,value是password,支持多个key、value;可选配置 PLUGINKIT_AUTH_REALM 以设置提示信息。
示例:
from flask_pluginkit import Flask, blueprint, PluginManager app = Flask(__name__) pm = PluginManager(app) app.config.update( PLUGINKIT_AUTH_METHOD="BASIC", PLUGINKIT_AUTH_USERS=dict(admin="admin", test="test") ) app.register_blueprint(blueprint, url_prefix='/pluginmanager')
TOKEN
这个要求浏览器端携带一个认证头,头的字段由应用程序配置项 PLUGINKIT_AUTH_TOKENFIELD 定义,默认值是AccessToken,同时要求配置一个名叫 PLUGINKIT_AUTH_CHECKTOKEN 的函数或类方法,这个函数要接收一个token参数,Flask-PluginKit会执行此函数,结果非0非空时通过验证。
示例:
from flask_pluginkit import Flask, blueprint, PluginManager app = Flask(__name__) pm = PluginManager() pm.init_app(app) def check_token(token): if token == 'test': return True app.config.update( PLUGINKIT_AUTH_METHOD="TOKEN", PLUGINKIT_AUTH_CHECKTOKEN=check_token ) app.register_blueprint(blueprint, url_prefix='/pluginmanager')
FUNC
这应该是最简单的了,由应用程序配置项 PLUGINKIT_AUTH_FUNC 定义一个函数或类方法,没有参数,执行结果非0非空时验证通过。
示例:
from flask_pluginkit import Flask, blueprint, PluginManager app = Flask(__name__) PluginManager(app) app.config.update( PLUGINKIT_AUTH_METHOD="FUNC", PLUGINKIT_AUTH_FUNC=lambda :True ) app.register_blueprint(blueprint, url_prefix='/pluginmanager')
PLUGINKIT_AUTH_AID_METHOD ,支持一种类型的值。
IP
Flask-PluginKit会获取客户端ip,要求应用程序配置 PLUGINKIT_AUTH_IP_WHITELIST 定义ip白名单,配置 PLUGINKIT_AUTH_IP_BLACKLIST 定义ip黑名单,两个数据类型都是list,只有ip在白名单且不在黑名单时,验证通过。
示例:
from flask_pluginkit import Flask, blueprint, PluginManager app = Flask(__name__) PluginManager(app) app.config.update( PLUGINKIT_AUTH_AID_METHOD="IP", PLUGINKIT_AUTH_IP_WHITELIST=["127.0.0.1"] ) app.register_blueprint(blueprint, url_prefix='/pluginmanager')
备注
一个应用程序中,主要方法的四种类型只能使用一种或不使用;辅助方法可以同时与主要方法一起使用,也可以单独使用;无论如何,必须有一种验证方法,否则页面提示权限拒绝。