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