| New file |
| | |
| | | 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() |