reset_passwords.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #!/usr/bin/env python3
  2. """
  3. 车牌识别系统 - 用户密码重置/创建脚本
  4. fix24 v29 (2026-07-05)
  5. 用法:
  6. cd /opt/openAI/project/003.PlateRecAPP
  7. python3 reset_passwords.py
  8. 功能:
  9. - 使用 data/auth.db 认证数据库
  10. - 创建或更新两个用户账号
  11. - 普通用户 zhonjin (role=0)
  12. - 超级管理员 admin (role=2)
  13. - 同时修复 config.ini 中的 auth db_path 指向正确路径
  14. """
  15. import sqlite3
  16. import sys
  17. import os
  18. import configparser
  19. try:
  20. import bcrypt
  21. except ImportError:
  22. print("正在安装 bcrypt 库...")
  23. os.system(f"{sys.executable} -m pip install bcrypt -q")
  24. import bcrypt
  25. # ==================== 配置 ====================
  26. # 候选数据库路径(按优先级排列)
  27. DB_CANDIDATES = [
  28. "data/auth.db", # fix24-v29: 唯一正确的认证数据库路径
  29. ]
  30. CONFIG_FILE = "config.ini"
  31. USERS = [
  32. {
  33. "username": "zhonjin",
  34. "password": "zhonjin",
  35. "role": 0, # 0=普通用户
  36. "display": "普通用户"
  37. },
  38. {
  39. "username": "admin",
  40. "password": "zhonjin188A",
  41. "role": 2, # 2=超级管理员
  42. "display": "超级管理员"
  43. },
  44. ]
  45. # Bcrypt cost factor (与 config.ini 中 bcrypt_cost 一致)
  46. BCRYPT_COST = 12
  47. # ==================== 工具函数 ====================
  48. def hash_password(password: str) -> str:
  49. """使用 bcrypt 生成密码哈希"""
  50. salt = bcrypt.gensalt(rounds=BCRYPT_COST)
  51. return bcrypt.hashpw(password.encode('utf-8'), salt).decode('utf-8')
  52. def find_auth_db() -> str:
  53. """自动检测正确的认证数据库"""
  54. for db_path in DB_CANDIDATES:
  55. if os.path.exists(db_path):
  56. try:
  57. conn = sqlite3.connect(db_path)
  58. cursor = conn.cursor()
  59. cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='users'")
  60. if cursor.fetchone():
  61. conn.close()
  62. return db_path
  63. conn.close()
  64. except Exception:
  65. continue
  66. # 都不存在,返回第一个候选(让程序创建)
  67. return DB_CANDIDATES[0]
  68. def fix_config_ini(correct_db_path: str):
  69. """修复 config.ini 中的 auth db_path"""
  70. if not os.path.exists(CONFIG_FILE):
  71. print(f"⚠️ 配置文件不存在: {CONFIG_FILE},跳过配置修复")
  72. return
  73. with open(CONFIG_FILE, 'r') as f:
  74. content = f.read()
  75. # 检查 [auth] 段中的 db_path
  76. lines = content.split('\n')
  77. new_lines = []
  78. in_auth_section = False
  79. db_path_found = False
  80. for line in lines:
  81. stripped = line.strip()
  82. if stripped.lower() == '[auth]':
  83. in_auth_section = True
  84. new_lines.append(line)
  85. continue
  86. if in_auth_section and stripped.startswith('['):
  87. in_auth_section = False
  88. if in_auth_section and stripped.lower().startswith('db_path'):
  89. db_path_found = True
  90. new_lines.append(f'db_path={correct_db_path}')
  91. print(f"🔧 config.ini: db_path 已更新为 {correct_db_path}")
  92. else:
  93. new_lines.append(line)
  94. if not db_path_found:
  95. # 如果没找到 db_path,在 [auth] 段的 enabled 后面添加
  96. final_lines = []
  97. for line in new_lines:
  98. final_lines.append(line)
  99. if line.strip().lower().startswith('enabled') and in_auth_section:
  100. # 这里有个问题:in_auth_section 可能已经被重置了
  101. pass
  102. # 简单处理:直接在文件末尾的 [auth] 段添加
  103. print(f"⚠️ config.ini [auth] 段未找到 db_path,请手动添加: db_path={correct_db_path}")
  104. else:
  105. with open(CONFIG_FILE, 'w') as f:
  106. f.write('\n'.join(new_lines))
  107. # ==================== 主逻辑 ====================
  108. def main():
  109. # 自动检测正确的数据库
  110. db_path = find_auth_db()
  111. print(f"📂 认证数据库: {os.path.abspath(db_path)}")
  112. print(f"🔐 Bcrypt cost: {BCRYPT_COST}")
  113. print()
  114. # 确保 data/ 目录存在(如果需要创建新数据库)
  115. db_dir = os.path.dirname(db_path)
  116. if db_dir and not os.path.exists(db_dir):
  117. os.makedirs(db_dir, exist_ok=True)
  118. conn = sqlite3.connect(db_path)
  119. cursor = conn.cursor()
  120. # 确保 users 表存在
  121. cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='users'")
  122. if not cursor.fetchone():
  123. print("📋 创建 users 表...")
  124. cursor.execute("""
  125. CREATE TABLE users (
  126. id INTEGER PRIMARY KEY AUTOINCREMENT,
  127. username TEXT UNIQUE NOT NULL,
  128. password_hash TEXT NOT NULL,
  129. role INTEGER DEFAULT 0,
  130. enabled INTEGER DEFAULT 1,
  131. failed_attempts INTEGER DEFAULT 0,
  132. locked_until INTEGER DEFAULT 0,
  133. created_at TEXT DEFAULT CURRENT_TIMESTAMP,
  134. updated_at TEXT DEFAULT CURRENT_TIMESTAMP
  135. )
  136. """)
  137. conn.commit()
  138. for user in USERS:
  139. username = user["username"]
  140. password = user["password"]
  141. role = user["role"]
  142. display = user["display"]
  143. # 生成密码哈希
  144. pw_hash = hash_password(password)
  145. # 检查用户是否已存在
  146. cursor.execute("SELECT id, role FROM users WHERE username = ?", (username,))
  147. existing = cursor.fetchone()
  148. if existing:
  149. # 更新密码和角色
  150. cursor.execute(
  151. "UPDATE users SET password_hash = ?, role = ?, enabled = 1, "
  152. "failed_attempts = 0, locked_until = 0, updated_at = CURRENT_TIMESTAMP "
  153. "WHERE username = ?",
  154. (pw_hash, role, username)
  155. )
  156. print(f"✅ [{display}] {username} — 密码已更新 (role={role})")
  157. else:
  158. # 创建新用户
  159. cursor.execute(
  160. "INSERT INTO users (username, password_hash, role, enabled, "
  161. "failed_attempts, locked_until, created_at, updated_at) "
  162. "VALUES (?, ?, ?, 1, 0, 0, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)",
  163. (username, pw_hash, role)
  164. )
  165. print(f"✅ [{display}] {username} — 用户已创建 (role={role})")
  166. conn.commit()
  167. conn.close()
  168. # 修复 config.ini
  169. print()
  170. fix_config_ini(db_path)
  171. print()
  172. print("=" * 50)
  173. print("🎉 密码重置完成!")
  174. print()
  175. print("账号信息:")
  176. print(f" 普通用户: zhonjin / zhonjin")
  177. print(f" 超级管理员: admin / zhonjin188A")
  178. print()
  179. print("📌 认证数据库: " + os.path.abspath(db_path))
  180. print()
  181. print("⚠️ 请确认 config.ini [auth] 段:")
  182. print(f" db_path={db_path}")
  183. print("=" * 50)
  184. if __name__ == "__main__":
  185. main()