import tkinter as tk from tkinter import messagebox, simpledialog, ttk import pymysql from Crypto.Cipher import AES import base64 import json import os VUE_APP_EncryptPrivateValue = "12345678abcdefgh" HISTORY_FILE = "username_history.json" class PasswordQueryApp: def __init__(self, root): self.root = root self.root.title("密码查询工具") self.database_info_file = "database_info.json" self.database_info = self.load_database_info() self.create_maintenance_page() self.create_query_page() self.update_username_menu() def load_database_info(self): try: with open(self.database_info_file, 'r') as f: return json.load(f) except FileNotFoundError: return {} def save_database_info(self): with open(self.database_info_file, 'w') as f: json.dump(self.database_info, f, indent=4) def create_maintenance_page(self): maintenance_frame = tk.LabelFrame(self.root, text="数据库信息维护") maintenance_frame.pack(fill="both", expand="yes", padx=10, pady=10) tk.Label(maintenance_frame, text="单位名称:").grid(row=0, column=0, sticky="w") self.unit_name_entry = tk.Entry(maintenance_frame) self.unit_name_entry.grid(row=0, column=1, padx=5, pady=5) tk.Label(maintenance_frame, text="MySQL 主机:").grid(row=1, column=0, sticky="w") self.host_entry = tk.Entry(maintenance_frame) self.host_entry.grid(row=1, column=1, padx=5, pady=5) tk.Label(maintenance_frame, text="MySQL 端口:").grid(row=2, column=0, sticky="w") self.port_entry = tk.Entry(maintenance_frame) self.port_entry.grid(row=2, column=1, padx=5, pady=5) self.port_entry.insert(0, "3306") tk.Label(maintenance_frame, text="MySQL 用户名:").grid(row=3, column=0, sticky="w") self.user_entry = tk.Entry(maintenance_frame) self.user_entry.grid(row=3, column=1, padx=5, pady=5) tk.Label(maintenance_frame, text="MySQL 密码:").grid(row=4, column=0, sticky="w") self.password_entry = tk.Entry(maintenance_frame, show="*") self.password_entry.grid(row=4, column=1, padx=5, pady=5) tk.Label(maintenance_frame, text="数据库名:").grid(row=5, column=0, sticky="w") self.db_name_entry = tk.Entry(maintenance_frame) self.db_name_entry.grid(row=5, column=1, padx=5, pady=5) tk.Label(maintenance_frame, text="用户表名:").grid(row=6, column=0, sticky="w") self.table_name_entry = tk.Entry(maintenance_frame) self.table_name_entry.grid(row=6, column=1, padx=5, pady=5) self.table_name_entry.insert(0, "sys_user") tk.Label(maintenance_frame, text="用户名列名:").grid(row=7, column=0, sticky="w") self.username_col_entry = tk.Entry(maintenance_frame) self.username_col_entry.grid(row=7, column=1, padx=5, pady=5) self.username_col_entry.insert(0, "login_name") tk.Label(maintenance_frame, text="密码列名:").grid(row=8, column=0, sticky="w") self.password_col_entry = tk.Entry(maintenance_frame) self.password_col_entry.grid(row=8, column=1, padx=5, pady=5) self.password_col_entry.insert(0, "plain_text") save_button = tk.Button(maintenance_frame, text="保存信息", command=self.save_database_info_action) save_button.grid(row=9, columnspan=2, pady=10) def update_username_menu(self): history = self.load_history() menu = self.username_menu["menu"] menu.delete(0, "end") for name in history: menu.add_command(label=name, command=lambda value=name: self.username_entry.delete(0, tk.END) or self.username_entry.insert(0, value)) def save_database_info_action(self): unit_name = self.unit_name_entry.get().strip() if unit_name == "": messagebox.showerror("错误", "单位名称为必填项") return self.database_info[unit_name] = { "host": self.host_entry.get().strip(), "port": self.port_entry.get().strip(), "user": self.user_entry.get().strip(), "password": self.password_entry.get().strip() or "", "db_name": self.db_name_entry.get().strip(), "table_name": self.table_name_entry.get().strip(), "username_col": self.username_col_entry.get().strip(), "password_col": self.password_col_entry.get().strip() } self.save_database_info() self.update_username_menu() messagebox.showinfo("成功", "数据库信息保存成功") def create_query_page(self): query_frame = tk.LabelFrame(self.root, text="密码查询") query_frame.pack(fill="both", expand="yes", padx=10, pady=10) tk.Label(query_frame, text="选择单位名称:").grid(row=0, column=0, sticky="w") self.unit_name_var = tk.StringVar(value="请选择单位") self.unit_name_dropdown = tk.OptionMenu(query_frame, self.unit_name_var, *self.database_info.keys()) self.unit_name_dropdown.grid(row=0, column=1, padx=5, pady=5) tk.Label(query_frame, text="输入用户名:").grid(row=1, column=0, sticky="w") self.username_entry = tk.Entry(query_frame) self.username_entry.grid(row=1, column=1, padx=5, pady=5) query_button = tk.Button(query_frame, text="查询密码", command=self.query_password_action) query_button.grid(row=2, columnspan=2, pady=10) self.password_var = tk.StringVar() tk.Label(query_frame, text="密码:").grid(row=3, column=0, sticky="w") self.password_entry_login = tk.Entry(query_frame, textvariable=self.password_var, state="readonly") self.password_entry_login.grid(row=3, column=1, padx=5, pady=5) copy_button = tk.Button(query_frame, text="复制密码", command=self.copy_password) copy_button.grid(row=4, column=0, pady=10) reset_button = tk.Button(query_frame, text="重置", command=self.reset_fields) reset_button.grid(row=4, column=1, pady=10) # 用户名下拉菜单 tk.Label(query_frame, text="选择用户名:").grid(row=5, column=0, sticky="w") self.username_menu_var = tk.StringVar() self.username_menu_var.set("选择用户名") self.username_menu = tk.OptionMenu(query_frame, self.username_menu_var, *self.load_history()) self.username_menu.grid(row=5, column=1, padx=5, pady=5) def query_password_action(self): unit_name = self.unit_name_var.get() username = self.username_entry.get().strip() if unit_name not in self.database_info: messagebox.showerror("错误", "请选择有效的单位名称") return db_info = self.database_info[unit_name] try: conn = pymysql.connect( host=db_info["host"], port=int(db_info["port"]), user=db_info["user"], password=db_info["password"], database=db_info["db_name"] ) cursor = conn.cursor() query = f"SELECT {db_info['username_col']}, {db_info['password_col']} FROM {db_info['table_name']} WHERE {db_info['username_col']} = %s" cursor.execute(query, (username,)) result = cursor.fetchone() if result: username_db, password = result if password is not None: decrypted_password = self.decrypt_password(username_db, password) self.password_var.set(decrypted_password) else: messagebox.showinfo("未找到", "未找到该用户名对应的密码") else: messagebox.showinfo("未找到", "未找到该用户名对应的密码") cursor.close() conn.close() except pymysql.MySQLError as err: messagebox.showerror("数据库错误", f"错误: {err}") def decrypt_password(self, username, password): try: user_info = self.get_user_info(username) if user_info: encrypted_password, encryption_key = user_info return self.decrypt(encrypted_password, encryption_key) else: return "用户信息不完整或不存在" except Exception as e: return f"解密错误: {e}" def decrypt(self, encrypted_password, encryption_key): try: key = encryption_key.encode('utf-8') iv = VUE_APP_EncryptPrivateValue.encode('utf-8') encrypted_password = base64.b64decode(encrypted_password) cipher = AES.new(key, AES.MODE_CBC, iv) decrypted = cipher.decrypt(encrypted_password) unpadded_text = decrypted.rstrip(b'\0').decode('utf-8') return unpadded_text except Exception as e: return f"解密错误: {e}" def get_user_info(self, username): unit_name = self.unit_name_var.get() if unit_name not in self.database_info: return None db_info = self.database_info[unit_name] try: conn = pymysql.connect( host=db_info["host"], port=int(db_info["port"]), user=db_info["user"], password=db_info["password"], database=db_info["db_name"] ) cursor = conn.cursor() cursor.execute(f"SELECT {db_info['username_col']}, {db_info['password_col']} FROM {db_info['table_name']} WHERE {db_info['username_col']} = %s", (username,)) result = cursor.fetchone() conn.close() return result except pymysql.MySQLError as err: messagebox.showerror("数据库错误", f"错误: {err}") return None def copy_password(self): decrypted_password = self.password_var.get() if decrypted_password: self.root.clipboard_clear() self.root.clipboard_append(decrypted_password) messagebox.showinfo("复制成功", "密码已复制到剪贴板") def reset_fields(self): self.username_entry.delete(0, tk.END) self.password_var.set("") self.unit_name_var.set("请选择单位") def load_history(self): if os.path.exists(HISTORY_FILE): with open(HISTORY_FILE, 'r') as f: history = json.load(f) else: history = [] return history def save_history(self, history): with open(HISTORY_FILE, 'w') as f: json.dump(history, f) if __name__ == "__main__": root = tk.Tk() app = PasswordQueryApp(root) root.mainloop()