feat(security): make default web UI admin username randomly generated by default instead of using hardcoded 'admin'

This commit is contained in:
baoweise
2026-05-28 22:40:20 +08:00
parent 4ebe42e4ce
commit 54bf62369b
2 changed files with 35 additions and 10 deletions
+17 -9
View File
@@ -346,7 +346,7 @@ def print_status():
login_ip = "127.0.0.1" if cfg.get("host") == "127.0.0.1" else get_public_ip() login_ip = "127.0.0.1" if cfg.get("host") == "127.0.0.1" else get_public_ip()
print(format_line("网页登录地址", f"{yellow}http://{login_ip}:{ui_port}/{secret_path}/{reset}")) print(format_line("网页登录地址", f"{yellow}http://{login_ip}:{ui_port}/{secret_path}/{reset}"))
print(format_line("网页管理账号", cfg.get("username", "admin"))) print(format_line("网页管理账号", cfg.get("username", "未配置")))
curr_pwd = cfg.get("password", "") curr_pwd = cfg.get("password", "")
masked_pwd = curr_pwd if len(curr_pwd) <= 4 else curr_pwd[:3] + "********" + curr_pwd[-2:] masked_pwd = curr_pwd if len(curr_pwd) <= 4 else curr_pwd[:3] + "********" + curr_pwd[-2:]
print(format_line("网页管理密码", masked_pwd)) print(format_line("网页管理密码", masked_pwd))
@@ -553,7 +553,7 @@ def configure_credentials():
print("=======================================================") print("=======================================================")
print(" 管理账号密码管理 ") print(" 管理账号密码管理 ")
print("=======================================================") print("=======================================================")
curr_uname = cfg.get('username', 'admin') curr_uname = cfg.get('username', '未配置')
curr_pwd = cfg.get('password', '') curr_pwd = cfg.get('password', '')
masked_pwd = curr_pwd if len(curr_pwd) <= 4 else curr_pwd[:3] + "********" + curr_pwd[-2:] masked_pwd = curr_pwd if len(curr_pwd) <= 4 else curr_pwd[:3] + "********" + curr_pwd[-2:]
print(f"当前管理账号: {curr_uname}") print(f"当前管理账号: {curr_uname}")
@@ -567,9 +567,9 @@ def configure_credentials():
key = getch() key = getch()
if key == '1': if key == '1':
print("\033[H\033[J", end="") print("\033[H\033[J", end="")
new_uname = input("请输入新管理账号 (回车默认 admin): ").strip() new_uname = input(f"请输入新管理账号 (回车默认 {curr_uname}): ").strip()
if not new_uname: if not new_uname:
new_uname = "admin" new_uname = curr_uname
new_pwd = input("请输入新管理密码 (不能为空): ").strip() new_pwd = input("请输入新管理密码 (不能为空): ").strip()
if not new_pwd: if not new_pwd:
print("错误: 密码不能为空!") print("错误: 密码不能为空!")
@@ -642,7 +642,7 @@ def get_status_state():
return ( return (
cfg.get("port", 8787), cfg.get("port", 8787),
cfg.get("secret_path", "EJsW2EeBo9lY"), cfg.get("secret_path", "EJsW2EeBo9lY"),
cfg.get("username", "admin"), cfg.get("username", "未配置"),
cfg.get("password", ""), cfg.get("password", ""),
cfg.get("host", "0.0.0.0"), cfg.get("host", "0.0.0.0"),
state.get("is_connecting", False), state.get("is_connecting", False),
@@ -783,7 +783,15 @@ while True:
print(pwd) print(pwd)
break break
") ")
UI_USERNAME="admin" UI_USERNAME=$(python3 -c "
import random, string
chars = string.ascii_letters + string.digits
while True:
uname = ''.join(random.choices(chars, k=12))
if uname[0].isalpha() and any(c.islower() for c in uname) and any(c.isupper() for c in uname) and any(c.isdigit() for c in uname):
print(uname)
break
")
if [[ "$is_custom" =~ ^[Yy]$ ]]; then if [[ "$is_custom" =~ ^[Yy]$ ]]; then
# Step-by-step custom inputs # Step-by-step custom inputs
@@ -817,7 +825,7 @@ while True:
done done
# 3. Custom login username and password # 3. Custom login username and password
read -p "请输入登录账号 [默认 admin]: " input_user read -p "请输入登录账号 [默认 $UI_USERNAME]: " input_user
if [ -n "$input_user" ]; then if [ -n "$input_user" ]; then
UI_USERNAME=$input_user UI_USERNAME=$input_user
fi fi
@@ -891,13 +899,13 @@ if [ -z "$ACTIVE_ID" ]; then
fi fi
SECRET_PATH="EJsW2EeBo9lY" SECRET_PATH="EJsW2EeBo9lY"
USERNAME="admin" USERNAME="未配置"
PASSWORD="未配置" PASSWORD="未配置"
UI_PORT=8787 UI_PORT=8787
AUTH_FILE="${INSTALL_DIR}/vpngate_data/ui_auth.json" AUTH_FILE="${INSTALL_DIR}/vpngate_data/ui_auth.json"
if [ -f "$AUTH_FILE" ]; then if [ -f "$AUTH_FILE" ]; then
SECRET_PATH=$(python3 -c "import json; print(json.load(open('$AUTH_FILE')).get('secret_path', 'EJsW2EeBo9lY'))" 2>/dev/null || echo "EJsW2EeBo9lY") SECRET_PATH=$(python3 -c "import json; print(json.load(open('$AUTH_FILE')).get('secret_path', 'EJsW2EeBo9lY'))" 2>/dev/null || echo "EJsW2EeBo9lY")
USERNAME=$(python3 -c "import json; print(json.load(open('$AUTH_FILE')).get('username', 'admin'))" 2>/dev/null || echo "admin") USERNAME=$(python3 -c "import json; print(json.load(open('$AUTH_FILE')).get('username', '未配置'))" 2>/dev/null || echo "未配置")
PASSWORD=$(python3 -c "import json; print(json.load(open('$AUTH_FILE')).get('password', '未配置'))" 2>/dev/null || echo "未配置") PASSWORD=$(python3 -c "import json; print(json.load(open('$AUTH_FILE')).get('password', '未配置'))" 2>/dev/null || echo "未配置")
UI_PORT=$(python3 -c "import json; print(json.load(open('$AUTH_FILE')).get('port', 8787))" 2>/dev/null || echo "8787") UI_PORT=$(python3 -c "import json; print(json.load(open('$AUTH_FILE')).get('port', 8787))" 2>/dev/null || echo "8787")
fi fi
+18 -1
View File
@@ -92,11 +92,24 @@ def generate_random_password() -> str:
if has_lower and has_upper and has_digit: if has_lower and has_upper and has_digit:
return pwd return pwd
def generate_random_username() -> str:
import string
chars = string.ascii_letters + string.digits
while True:
uname = "".join(random.choices(chars, k=12))
# Ensure it starts with a letter and contains at least one lowercase, one uppercase, and one digit
if uname[0].isalpha():
has_lower = any(c.islower() for c in uname)
has_upper = any(c.isupper() for c in uname)
has_digit = any(c.isdigit() for c in uname)
if has_lower and has_upper and has_digit:
return uname
def load_ui_config() -> dict[str, Any]: def load_ui_config() -> dict[str, Any]:
with lock: with lock:
auth_file = DATA_DIR / "ui_auth.json" auth_file = DATA_DIR / "ui_auth.json"
config = { config = {
"username": "admin", "username": "",
"secret_path": "EJsW2EeBo9lY", "secret_path": "EJsW2EeBo9lY",
"password": "", "password": "",
"host": "0.0.0.0", "host": "0.0.0.0",
@@ -111,6 +124,10 @@ def load_ui_config() -> dict[str, Any]:
except Exception: except Exception:
pass pass
if not config.get("username"):
config["username"] = generate_random_username()
updated = True
if not config.get("password"): if not config.get("password"):
config["password"] = generate_random_password() config["password"] = generate_random_password()
updated = True updated = True