使用 pywebio 实现简易的工具箱网页(带登录态)
使用 pywebio 实现简易的工具箱网页(带登录态)
背景说明
简单做一个网页放个人服务器,展示一些自己常用的工具脚本,而且支持直接在网页运行工具,这样方便自己随时随地需要触发一些任务。
由于是直接在个人服务器上运行脚本,需要有一定的权限控制,避免被其他人误操作。因此采用 pywebio 这样一个轻量级的工具,好处是不用去写一个单独的前端,而且大部份工具脚本都是 python 编写,调用方便。
效果
- 登录页面
- 应用列表(登录后)
- 应用页面(app1)
import functools
import pywebio
from pywebio.input import *
from pywebio.output import *
from pywebio.session import *
from pywebio.platform.page import get_static_index_content
from tornado.web import create_signed_value, decode_signed_value
class LocalStorage():
@staticmethod
def set(key, value):
run_js("localStorage.setItem(key, value)", key=key, value=value)
@staticmethod
def get(key):
return eval_js("localStorage.getItem(key)", key=key)
@staticmethod
def remove(key):
print(f"remove {key}")
run_js("localStorage.removeItem(key)", key=key)
# 定义一个装饰,用于检查用户是否已登录
def login_required(func):
# 使用 functools.wraps,保持函数名称不变
@functools.wraps(func)
def warpper(*args, **kwargs):
token = LocalStorage().get('token')
print(f"token = {token}")
username = decode_signed_value(SECRET, 'token', token, max_age_days=7)
print(f"username = {username}")
if not token or not username: # no token or token validation failed
return login()
return func(*args, **kwargs)
return warpper
def check_user(username, password):
# 检查用户名密码是否正确
return True
# 加盐
SECRET = "encryption salt value"
def login():
"""Persistence auth
Use a to signed token mechanism to generate a token store in user's web browser
"""
user = input_group('Login', [
input("Username", name='username'),
input("Password", type=PASSWORD, name='password'),
])
username = user['username']
if check_user(username, user['password']):
signed = create_signed_value(SECRET, 'token', user['username']).decode("utf-8")
LocalStorage().set('token', signed)
LocalStorage().set('username', user['username'])
return index()
else:
toast('Wrong password!', color='error')
return index()
@login_required
def app1():
""" 应用1
应用1的说明
"""
username = LocalStorage().get("username")
put_markdown(f"# Hello {username}\nThis is a message from app1")
@login_required
def app2():
""" 应用2
应用1的说明
"""
username = LocalStorage().get("username")
put_markdown(f"# Hello {username}\nThis is a message from app2")
@login_required
def logout():
""" 退出
退出当前登录状态
"""
LocalStorage().remove('token')
toast("Logout Success !!", color='success')
clear()
return index()
@login_required
def index():
""" 首页
"""
applications = {f.__name__: f for f in apps if f.__name__ not in ['index']}
content = get_static_index_content(applications)
put_html(content)
if __name__ == '__main__':
apps = [index, app1, app2, logout]
pywebio.start_server(apps, port=80)