device_id.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. # device_id.py
  2. import socket
  3. import uuid
  4. from typing import Optional, Dict, List
  5. import winreg
  6. import subprocess
  7. import os
  8. import hashlib
  9. import socket
  10. import uuid
  11. import platform
  12. import re
  13. def get_windows_device_id() -> Optional[str]:
  14. """Windows: 获取BIOS UUID"""
  15. uuid = None
  16. # 方法1: 使用wmic命令
  17. try:
  18. result = subprocess.run(
  19. ["wmic", "csproduct", "get", "uuid"],
  20. capture_output=True,
  21. text=True,
  22. shell=True,
  23. creationflags=subprocess.CREATE_NO_WINDOW,
  24. )
  25. if result.returncode == 0:
  26. # 按行分割,过滤空行
  27. lines = [
  28. line.strip()
  29. for line in result.stdout.strip().split("\n")
  30. if line.strip()
  31. ]
  32. # 找到UUID行
  33. for line in lines:
  34. if len(line) == 36 and line.count("-") == 4:
  35. uuid = line
  36. break
  37. except Exception as e:
  38. print(f"WMIC获取失败: {e}")
  39. # 方法2: 如果wmic失败,使用PowerShell
  40. if not uuid:
  41. try:
  42. result = subprocess.run(
  43. [
  44. "powershell",
  45. "-Command",
  46. "(Get-WmiObject -Class Win32_ComputerSystemProduct).UUID",
  47. ],
  48. capture_output=True,
  49. text=True,
  50. shell=True,
  51. )
  52. if result.returncode == 0:
  53. uuid = result.stdout.strip()
  54. except Exception as e:
  55. print(f"PowerShell获取失败: {e}")
  56. # 方法3: 如果PowerShell也失败,使用注册表
  57. if not uuid:
  58. try:
  59. with winreg.OpenKey(
  60. winreg.HKEY_LOCAL_MACHINE,
  61. r"SOFTWARE\Microsoft\Windows NT\CurrentVersion",
  62. ) as key:
  63. uuid, _ = winreg.QueryValueEx(key, "ProductId")
  64. except Exception as e:
  65. print(f"注册表获取失败: {e}")
  66. return uuid
  67. def get_linux_machine_id() -> Optional[str]:
  68. """Linux: 获取机器ID"""
  69. machine_id_paths = [
  70. "/etc/machine-id", # systemd系统
  71. "/var/lib/dbus/machine-id", # 老版本
  72. ]
  73. for path in machine_id_paths:
  74. if os.path.exists(path):
  75. try:
  76. with open(path, "r") as f:
  77. machine_id = f.read().strip()
  78. if machine_id:
  79. return machine_id
  80. except:
  81. continue
  82. return None
  83. def get_linux_system_uuid() -> Optional[str]:
  84. """Linux: 获取系统UUID"""
  85. try:
  86. if os.path.exists("/sys/devices/virtual/dmi/id/product_uuid"):
  87. with open("/sys/devices/virtual/dmi/id/product_uuid", "r") as f:
  88. uuid = f.read().strip()
  89. if uuid and len(uuid) == 36:
  90. return uuid
  91. except:
  92. pass
  93. return None
  94. def get_mac_serial_number() -> Optional[str]:
  95. """macOS: 获取序列号"""
  96. try:
  97. result = subprocess.run(
  98. ["system_profiler", "SPHardwareDataType"], capture_output=True, text=True
  99. )
  100. if result.returncode == 0:
  101. output = result.stdout
  102. for line in output.split("\n"):
  103. if "Serial Number" in line or "序列号" in line:
  104. parts = line.split(":")
  105. if len(parts) > 1:
  106. serial = parts[1].strip()
  107. if serial:
  108. return serial
  109. except:
  110. pass
  111. return None
  112. def get_platform_device_id() -> Optional[str]:
  113. """获取平台设备ID"""
  114. system = platform.system()
  115. if system == "Windows":
  116. return get_windows_device_id()
  117. elif system == "Linux":
  118. # 优先使用系统UUID
  119. uuid = get_linux_system_uuid()
  120. if uuid:
  121. return uuid
  122. # 回退到machine-id
  123. return get_linux_machine_id()
  124. elif system == "Darwin": # macOS
  125. return get_mac_serial_number()
  126. return None
  127. def get_device_id():
  128. """获取设备特征码"""
  129. device_id = get_platform_device_id()
  130. if device_id:
  131. # 清理设备ID
  132. clean_id = re.sub(r"[^a-zA-Z0-9]", "", device_id).upper()
  133. fingerprint = hashlib.sha256(clean_id.encode()).hexdigest()[:24].upper()
  134. else:
  135. # 回退方案
  136. info = {
  137. "hostname": socket.gethostname(),
  138. "system": platform.system(),
  139. "machine": platform.machine(),
  140. }
  141. fingerprint_data = "|".join([f"{k}:{v}" for k, v in sorted(info.items())])
  142. fingerprint = hashlib.sha256(fingerprint_data.encode()).hexdigest()[:24].upper()
  143. return fingerprint
  144. def get_device_info() -> Dict:
  145. """获取系统详细信息"""
  146. info = {}
  147. try:
  148. if platform.system() == "Windows":
  149. # 获取Windows产品ID
  150. with winreg.OpenKey(
  151. winreg.HKEY_LOCAL_MACHINE,
  152. r"SOFTWARE\Microsoft\Windows NT\CurrentVersion",
  153. ) as key:
  154. info["product_id"] = winreg.QueryValueEx(key, "ProductId")[0]
  155. info["product_name"] = winreg.QueryValueEx(key, "ProductName")[0]
  156. # 获取BIOS UUID
  157. result = subprocess.run(
  158. ["wmic", "csproduct", "get", "uuid"],
  159. capture_output=True,
  160. text=True,
  161. shell=True,
  162. creationflags=subprocess.CREATE_NO_WINDOW,
  163. )
  164. if result.returncode == 0:
  165. lines = [line.strip() for line in result.stdout.strip().split("\n")]
  166. # 过滤掉空行
  167. lines = [line for line in lines if line]
  168. if len(lines) > 1:
  169. uuid = lines[1] if len(lines) > 1 else lines[0]
  170. if uuid and uuid != "":
  171. info["bios_uuid"] = uuid
  172. # 获取主机名
  173. info["hostname"] = socket.gethostname()
  174. except Exception as e:
  175. info["error"] = str(e)
  176. return info
  177. if __name__ == "__main__":
  178. device_id = get_device_id()
  179. print(f"设备特征码: {device_id}")
  180. print(f"设备信息: {get_platform_device_id()}")
  181. with winreg.OpenKey(
  182. winreg.HKEY_LOCAL_MACHINE,
  183. r"SOFTWARE\Microsoft\Windows NT\CurrentVersion",
  184. ) as key:
  185. uuid, _ = winreg.QueryValueEx(key, "ProductId")
  186. print(f"Windows产品ID: {uuid}")
  187. # info = get_device_info()
  188. # for key, value in info.items():
  189. # print(f" {key}: {value}")
  190. system = platform.system()
  191. info = {
  192. "system": system,
  193. "release": platform.release(),
  194. "machine": platform.machine(),
  195. "node": platform.node(),
  196. "hostname": socket.gethostname(),
  197. }
  198. print(info)