From aa191ffd9082f8bd39b426fd95bd2faf442dd2c3 Mon Sep 17 00:00:00 2001 From: Codepy <1942171924@qq.com> Date: Tue, 9 Apr 2024 21:28:47 +0800 Subject: [PATCH 1/4] =?UTF-8?q?upd=EF=BC=9Atest=E5=88=86=E6=94=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/main.py b/main.py index 9426731..916bc8d 100644 --- a/main.py +++ b/main.py @@ -15,10 +15,6 @@ if f.Had("data/config/panel.json"): def index(id): if id == 1: return 'first' - elif id == 2: - return 'second' - elif id == 3: - return 'thrid' else: return 'hello world!' -- Gitee From fdd9ee7b08446139cae78de718fd6aa542959922 Mon Sep 17 00:00:00 2001 From: Codepy <1942171924@qq.com> Date: Sat, 13 Apr 2024 17:41:54 +0800 Subject: [PATCH 2/4] =?UTF-8?q?upd=EF=BC=9A=E5=BC=80=E6=9C=BA=E8=87=AA?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=20upd=EF=BC=9A=E5=AE=89=E8=A3=85=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +++ .idea/.gitignore | 3 --- .idea/misc.xml | 2 +- app/controller/index.py | 15 +++++++++++ app/controller/install.py | 27 +++++++++++++++---- app/utils/Config.py | 13 +++++++++ app/utils/Route.py | 12 +++++++++ app/utils/Service.py | 46 +++++++++++++++++++++++++++++++ install.sh | 0 main.py | 32 +++++++++++----------- public/static/css/login.css | 54 +++++++++++++++++++++++++++++++++++++ templates/login.html | 27 +++++++++++++++++++ 12 files changed, 209 insertions(+), 26 deletions(-) delete mode 100644 .idea/.gitignore create mode 100644 app/controller/index.py create mode 100644 app/utils/Config.py create mode 100644 app/utils/Route.py create mode 100644 app/utils/Service.py create mode 100644 install.sh create mode 100644 public/static/css/login.css create mode 100644 templates/login.html diff --git a/.gitignore b/.gitignore index 0966463..d7db213 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,10 @@ bin-release/ *.ipa *.apk .venv/ +.data/config/ +main.spec +.build/ +.dist/ # Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties` # should NOT be excluded as they contain compiler settings and other important # information for Eclipse / Flash Builder. diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 359bb53..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# 默认忽略的文件 -/shelf/ -/workspace.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index d72b3f9..3fe72cc 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/app/controller/index.py b/app/controller/index.py new file mode 100644 index 0000000..5ca2dc0 --- /dev/null +++ b/app/controller/index.py @@ -0,0 +1,15 @@ +from flask import Flask, Response +from app.utils import Route +from app.utils import Config + + +def service_start(): + app = Flask(__name__, template_folder='../../templates') + app.static_folder = "../../public/static" + # 获取配置文件 + cfg = Config.get_config() + print(cfg) + # 可以在路径内以/<参数名>的形式指定参数,默认接收到的参数类型是string + Route.get_route(app,cfg) + + app.run(port=cfg["port"]) diff --git a/app/controller/install.py b/app/controller/install.py index 442989f..7c48459 100644 --- a/app/controller/install.py +++ b/app/controller/install.py @@ -4,6 +4,8 @@ import json import random import string import hashlib +from app.utils import Service + def install(): system = sy.get_system_name() @@ -13,13 +15,19 @@ def install(): # 生成随机字母 username = ''.join(random.choices(string.ascii_letters, k=5)) pw = ''.join(random.choices(string.ascii_letters + string.digits, k=8)) - port = random.randint(8888, 8900) + port = random.randint(8888, 9000) ip = sy.get_system_ip() - print("用户名:", username, "\n密码:", pw, "\n端口:", port) - print("面板访问地址: http://" + ip + ":" + str(port) + "/") + # 生成随机安全入口 + safe_entry = ''.join(random.choices(string.ascii_letters, k=5)) + print("用户名:", username, "\n密码:", pw, "\n端口:", port, "\n安全入口:", safe_entry) + print("面板访问地址: http://" + ip + ":" + str(port) + "/" + safe_entry) # 写入文件 - json_data = {username: hashlib.sha256(pw.encode()).hexdigest(), "port": port} + json_data = { + username: hashlib.sha256(pw.encode()).hexdigest(), + "port": port, + "safe_entry": safe_entry, + } with open("./data/config/panel.json", 'w') as file: json.dump(json_data, file) @@ -37,7 +45,16 @@ def install(): print("文件权限设置成功") else: print("文件权限设置失败:", error.decode('utf-8')) + return False else: # 设置文件权限为root可读写,其它用户无法读写 os.chmod("./data/config/panel.json", 0o600) - print("安装完成") + + # 设置开机自启动 + service_name = "QPanel面板服务" + + service_file = Service.create_systemd_service(service_name) + if service_file: + return True + else: + return False diff --git a/app/utils/Config.py b/app/utils/Config.py new file mode 100644 index 0000000..95a5439 --- /dev/null +++ b/app/utils/Config.py @@ -0,0 +1,13 @@ +import json + +# JSON 文件路径 +def get_config(): + file_path = "./data/config/panel.json" + + # 打开 JSON 文件并读取数据 + with open(file_path, "r") as json_file: + # 使用 json 模块的 load() 方法将 JSON 数据解析为 Python 对象 + json_data = json.load(json_file) + + # 打印 JSON 对象 + return json_data diff --git a/app/utils/Route.py b/app/utils/Route.py new file mode 100644 index 0000000..35818bf --- /dev/null +++ b/app/utils/Route.py @@ -0,0 +1,12 @@ +from flask import render_template, send_from_directory + + +def get_route(app, cfg): + @app.route("/" + cfg["safe_entry"]) + def login(): + return render_template('login.html') + + @app.route('/static/') + def static_file(path): + # 使用send_from_directory函数来发送静态文件 + return send_from_directory(app.static_folder, path) diff --git a/app/utils/Service.py b/app/utils/Service.py new file mode 100644 index 0000000..6f3bc3c --- /dev/null +++ b/app/utils/Service.py @@ -0,0 +1,46 @@ +import os +from app.utils import System + + +def create_systemd_service(service_name): + if System.get_system_name() == "Linux": + print(1) + username = os.getlogin() # 获取当前用户名 + script_path = "/home/quick-panel/" + service_content = f"""\ + [Unit] + Description=My Python Script + After=network.target + + [Service] + User={username} + WorkingDirectory={os.path.dirname(script_path)} + ExecStart=/usr/bin/python3 {script_path} + Restart=always + + [Install] + WantedBy=multi-user.target + """ + service_file = f"/etc/systemd/system/{service_name}.service" + with open(service_file, 'w') as f: + f.write(service_content) + os.system(f"sudo systemctl daemon-reload") + os.system(f"sudo systemctl enable {service_name}.service") + return True + elif System.get_system_name() == "Windows": + + # Windows 系统下的服务创建逻辑 + import winreg + key = r"Software\Microsoft\Windows\CurrentVersion\Run" + try: + # 打开指定路径下的注册表项 + key_handle = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key, 0, winreg.KEY_WRITE) + # 设置注册表项的值 + winreg.SetValueEx(key_handle, "QPanel面板", 0, winreg.REG_SZ, "C:\Program Files\QPanel\main.exe") + # 关闭注册表项 + winreg.CloseKey(key_handle) + return True + except Exception as e: + print(f"Error creating startup entry: {e}") + return False + diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..e69de29 diff --git a/main.py b/main.py index 916bc8d..2930f55 100644 --- a/main.py +++ b/main.py @@ -1,33 +1,31 @@ +import subprocess + from flask import Flask, Response import app.utils.File as f import app.controller.install as paninstall - -app = Flask(__name__) - -# 可以在路径内以/<参数名>的形式指定参数,默认接收到的参数类型是string +from app.controller import index +import sys # 检测安装 if f.Had("data/config/panel.json"): print("已安装") - - - @app.route("/index/", ) - def index(id): - if id == 1: - return 'first' - else: - return 'hello world!' - - - if __name__ == '__main__': - app.run() + index.service_start() else: print("未安装面板") install = input("是否安装面板(y/n):") if install == "y": # 安装面板 print("开始安装面板...") - paninstall.install() + if paninstall.install(): + print("安装成功") + # 获取当前可执行文件的路径 + executable = sys.executable + # 重新启动当前程序 + subprocess.Popen([executable] + sys.argv) + # 退出当前程序 + sys.exit() + else: + print("安装失败") else: print("退出程序") diff --git a/public/static/css/login.css b/public/static/css/login.css new file mode 100644 index 0000000..2f5f060 --- /dev/null +++ b/public/static/css/login.css @@ -0,0 +1,54 @@ + body { + margin: 0; + padding: 0; + height: 100vh; + display: flex; + justify-content: center; + align-items: center; + background-color: #f5f9ff; + } + .form-container { + background-color: #e2f1ff; + padding: 20px; + border-radius: 10px; + /* box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.1); */ + } + .form-container h2 { + text-align: center; + } + .form-group { + margin-bottom: 20px; + padding-inline:50px + } + .form-group label { + display: block; + margin-bottom: 5px; + } + .form-group input { + width: 100%; + padding: 10px; + border: 2px solid #dde8ff; /* 使用基色设置边框 */ + border-radius: 5px; + box-sizing: border-box; + transition: border-color 0.3s ease; /* 添加过渡效果 */ + } + .form-group input:focus { + border-color: #6A9BFF; /* 使用悬浮色设置边框 */ + outline: none; + } + .form-group button { + width: 100%; + padding: 10px; + border: none; + border-radius: 5px; + background-color: #4A81FF; /* 使用基色设置背景色 */ + color: #fff; + cursor: pointer; + transition: background-color 0.3s ease; /* 添加过渡效果 */ + } + .form-group button:hover { + background-color: #6A9BFF; /* 使用悬浮色设置背景色 */ + } + .form-group button:active { + background-color: #2E5AD2; /* 使用点击色设置背景色 */ + } \ No newline at end of file diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..910b9f4 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,27 @@ + + + + + +QPanel登录 + + + +
+

QPanel登录

+
+
+ + +
+
+ + +
+
+ +
+
+
+ + -- Gitee From b71cd0f82b88b0b8c8d8e1947dc41b2596e1b98b Mon Sep 17 00:00:00 2001 From: Codepy <1942171924@qq.com> Date: Sat, 13 Apr 2024 18:41:40 +0800 Subject: [PATCH 3/4] =?UTF-8?q?upd=EF=BC=9A=E4=BC=AA=E8=A3=85=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=20upd=EF=BC=9A=E7=99=BB=E5=BD=95=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controller/api.py | 18 ++++++++++++++++ app/controller/index.py | 1 + app/controller/install.py | 2 ++ app/utils/Route.py | 25 ++++++++++++++++++++++- public/static/js/login.js | 43 +++++++++++++++++++++++++++++++++++++++ templates/404.html | 7 +++++++ templates/index.html | 0 templates/login.html | 1 + 8 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 app/controller/api.py create mode 100644 public/static/js/login.js create mode 100644 templates/404.html create mode 100644 templates/index.html diff --git a/app/controller/api.py b/app/controller/api.py new file mode 100644 index 0000000..32edff5 --- /dev/null +++ b/app/controller/api.py @@ -0,0 +1,18 @@ +from flask import jsonify, session +import hashlib +import json +def service(path, cfg, data): + if path == "login": + print(data) + if data["username"] in cfg: + # 登录用户名正确 + print(hashlib.sha256(data["pw"].encode()).hexdigest()) + if hashlib.sha256(data["pw"].encode()).hexdigest() == cfg[data["username"]]: + # 密码正确 + session['username'] = data["username"] + session['pw'] = hashlib.sha256(data["pw"].encode()).hexdigest() + return jsonify({'code': 200, 'msg': 'Login successful'}) + else: + return jsonify({'code': 401, 'msg': 'Wrong password'}) + else: + return jsonify({'code': 404, 'msg': 'User not found'}) diff --git a/app/controller/index.py b/app/controller/index.py index 5ca2dc0..15c3bd3 100644 --- a/app/controller/index.py +++ b/app/controller/index.py @@ -8,6 +8,7 @@ def service_start(): app.static_folder = "../../public/static" # 获取配置文件 cfg = Config.get_config() + app.secret_key = cfg["secret_key"] print(cfg) # 可以在路径内以/<参数名>的形式指定参数,默认接收到的参数类型是string Route.get_route(app,cfg) diff --git a/app/controller/install.py b/app/controller/install.py index 7c48459..cf329d9 100644 --- a/app/controller/install.py +++ b/app/controller/install.py @@ -17,6 +17,7 @@ def install(): pw = ''.join(random.choices(string.ascii_letters + string.digits, k=8)) port = random.randint(8888, 9000) ip = sy.get_system_ip() + secret_key = ''.join(random.choices(string.ascii_letters + string.digits, k=9)) # 生成随机安全入口 safe_entry = ''.join(random.choices(string.ascii_letters, k=5)) print("用户名:", username, "\n密码:", pw, "\n端口:", port, "\n安全入口:", safe_entry) @@ -27,6 +28,7 @@ def install(): username: hashlib.sha256(pw.encode()).hexdigest(), "port": port, "safe_entry": safe_entry, + "secret_key": secret_key } with open("./data/config/panel.json", 'w') as file: json.dump(json_data, file) diff --git a/app/utils/Route.py b/app/utils/Route.py index 35818bf..f75e769 100644 --- a/app/utils/Route.py +++ b/app/utils/Route.py @@ -1,7 +1,26 @@ -from flask import render_template, send_from_directory +from flask import render_template, send_from_directory, request, session, abort +from app.controller import api def get_route(app, cfg): + @app.before_request + def before_request_func(): + if "username"in session and "pw" in session: + if cfg[session.get('username')] != session.get('pw'): + # 未登录 + abort(404) + else: + # 未登录 + abort(404) + + @app.errorhandler(404) + def page_not_found(error): + return render_template('404.html'), 404 + + @app.route("/") + def home(): + return render_template('index.html') + @app.route("/" + cfg["safe_entry"]) def login(): return render_template('login.html') @@ -10,3 +29,7 @@ def get_route(app, cfg): def static_file(path): # 使用send_from_directory函数来发送静态文件 return send_from_directory(app.static_folder, path) + + @app.route('/api/post/', methods=['POST']) + def api_controller(path): + return api.service(path, cfg, request.json) diff --git a/public/static/js/login.js b/public/static/js/login.js new file mode 100644 index 0000000..748cd8f --- /dev/null +++ b/public/static/js/login.js @@ -0,0 +1,43 @@ +document.addEventListener("DOMContentLoaded", function() { + // 监听表单提交事件 + document.querySelector("form").addEventListener("submit", function(event) { + // 阻止默认表单提交行为 + event.preventDefault(); + + // 获取用户名和密码 + var username = document.getElementById("username").value; + var password = document.getElementById("password").value; + + // 构造要发送的数据对象 + var data = { + username: username, + pw: password + }; + + // 发送 POST 请求 + fetch("/api/post/login", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(data) + }) + .then(response => response.json()) + .then(data => { + if (data.code === 200) { + // 登录成功,可以进行相应的操作,比如跳转页面等 + console.log("登录成功"); + window.location.href = "/"; // 示例:跳转到仪表盘页面 + } else { + // 登录失败,处理错误 + console.error("登录失败"); + alert("登录失败,请检查用户名和密码!"); + } + }) + .catch(error => { + // 发生网络错误或其他异常 + console.error("发生错误", error); + alert("发生错误,请稍后重试!"); + }); + }); +}); diff --git a/templates/404.html b/templates/404.html new file mode 100644 index 0000000..6f17eaf --- /dev/null +++ b/templates/404.html @@ -0,0 +1,7 @@ + +404 Not Found + +

404 Not Found

+
nginx
+ + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..e69de29 diff --git a/templates/login.html b/templates/login.html index 910b9f4..c2e00d5 100644 --- a/templates/login.html +++ b/templates/login.html @@ -5,6 +5,7 @@ QPanel登录 +
-- Gitee From 857996a4cc8744dc33bc8ef62ec351d4117f885c Mon Sep 17 00:00:00 2001 From: Codepy <1942171924@qq.com> Date: Sat, 13 Apr 2024 19:06:01 +0800 Subject: [PATCH 4/4] =?UTF-8?q?bugfix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/utils/Route.py | 15 +++++++++++---- main.py | 1 - 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/utils/Route.py b/app/utils/Route.py index f75e769..c9e0ffe 100644 --- a/app/utils/Route.py +++ b/app/utils/Route.py @@ -5,13 +5,20 @@ from app.controller import api def get_route(app, cfg): @app.before_request def before_request_func(): + # 打印出所有路径参数及其值 + print(request.path) if "username"in session and "pw" in session: if cfg[session.get('username')] != session.get('pw'): - # 未登录 - abort(404) + if request.path != "/" + cfg["safe_entry"]: + if "/static" not in request.path and "/api/post/login" not in request.path: + # 未登录 + abort(404) else: - # 未登录 - abort(404) + if request.path != "/" + cfg["safe_entry"]: + if "/static" not in request.path and "/api/post/login" not in request.path: + # 未登录 + abort(404) + @app.errorhandler(404) def page_not_found(error): diff --git a/main.py b/main.py index 2930f55..2f362a1 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,5 @@ import subprocess -from flask import Flask, Response import app.utils.File as f import app.controller.install as paninstall from app.controller import index -- Gitee