Python密码输入阶段实时字符检测与合规提示动态变色的实现方法
实时密码输入检测实现方案
原有逻辑的核心限制
当前代码使用的getpass是系统级阻塞输入接口,仅在用户按下回车键提交后才会返回完整输入内容,无法在输入过程中逐字符捕获变化,自然也做不到实时更新提示行颜色。要实现目标需求,必须替换成逐字符读取的终端输入逻辑,配合ANSI终端控制序列动态刷新提示内容。
实现要点
- 跨平台兼容逐字符读取,分别处理Windows和类Unix系统的终端输入模式
- 保留密码输入不回显明文的安全特性,仅用占位符提示输入进度
- 每次捕获输入/退格操作后,立即重算所有校验维度的结果,动态切换对应提示行的颜色
- 严格沿用原有代码的OWASP校验规则,不修改判定标准
参考可运行代码
import os import sys import string from termcolor import colored # 跨平台逐字符输入兼容 def getch(): if os.name == 'nt': import msvcrt return msvcrt.getch().decode('utf-8', errors='ignore') else: import tty import termios fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setcbreak(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return ch # 实时拆分返回各校验维度结果 def get_password_check_result(password): uppercase_letters = string.ascii_uppercase lowercase_letters = string.ascii_lowercase digits = string.digits special_characters = "!@#$%^&*()-_" return { "length_pass": len(password) >= 8, "uppercase_pass": any(c in uppercase_letters for c in password), "lowercase_pass": any(c in lowercase_letters for c in password), "digit_pass": any(c in digits for c in password), "special_pass": any(c in special_characters for c in password) } # 动态重绘提示行 def render_prompt(check_result): # 清空光标下方的所有终端内容 sys.stdout.write("\033[J") prompt_list = [ ("* 需包含大写字符", check_result["uppercase_pass"]), ("* 需包含小写字符", check_result["lowercase_pass"]), ("* 需包含数字", check_result["digit_pass"]), ("* 需包含特殊字符 (!@#$%^&*()-_)", check_result["special_pass"]), ("* 长度需达到8位以上", check_result["length_pass"]) ] for prompt_text, is_passed in prompt_list: line_color = "green" if is_passed else "magenta" print(colored(prompt_text, line_color)) # 空行分隔提示区和输入区 print() print(colored("请输入主密码:", "blue"), end="", flush=True) if __name__ == "__main__": # 打印顶部标题 print(colored("根据OWASP 2021密码标准,主密码需满足以下要求:", "magenta")) current_pwd = "" # 初始渲染一次提示 render_prompt(get_password_check_result(current_pwd)) while True: input_char = getch() # 收到回车键,结束输入流程 if input_char in ('\n', '\r'): print() break # 收到退格键,删除已输入的最后一个字符 elif input_char in ('\b', '\x7f'): if len(current_pwd) > 0: current_pwd = current_pwd[:-1] # 光标回退一格,同步删除占位符 sys.stdout.write("\b \b") # 收到可打印字符,追加到密码串 elif input_char.isprintable(): current_pwd += input_char # 不回显明文密码,仅输出占位符 sys.stdout.write("*") sys.stdout.flush() # 光标上移到提示区顶部,准备重绘 sys.stdout.write("\033[F" * 7) render_prompt(get_password_check_result(current_pwd)) sys.stdout.flush() # 输入完成后的最终校验 final_result = get_password_check_result(current_pwd) if not all(final_result.values()): print(colored("密码未满足全部要求,请重新输入。\n", "yellow")) else: print(colored("主密码保存成功!", "green"))
运行说明
- 终端需支持ANSI转义序列,Windows 10 1511及以上版本的cmd、PowerShell默认满足要求
- 输入过程中不会回显明文密码,仅用星号占位,符合密码管理器的安全特性
- 每输入一个符合规则的字符,对应提示行立刻切换为绿色;删除字符导致某条规则不再满足时,提示行立刻恢复为原洋红色
内容的提问来源于stack exchange,提问作者Osama A. Al-Amarneh
相关产品推荐
相关产品推荐

