在使用Python的Tkinter库开发图形界面应用时,登录窗口中的密码输入框如果直接显示用户输入的字符,会带来明显的信息泄露风险。Tkinter为标准单行文本输入提供了Entry组件,通过配置它的show属性,就能让输入框以指定符号代替真实字符进行界面呈现,从而实现基础的加密输入效果。

一、Entry组件与show属性基础
Entry是Tkinter里最常用的文本录入控件,通常用来接收用户名、密码、验证码等短文本。它有很多配置项,其中show是一个专门控制“显示字符”的参数。如果不设置show,Entry会原样显示用户输入的内容;一旦设置了show,无论用户敲什么键,界面上出现的都是同一个替代字符。
从底层逻辑看,show只改变了控件的“绘制层”表现,并没有修改内部维护的字符串变量。也就是说,用户在键盘上输入的每一个字符都被正常记录到Entry的内部缓存中,程序调用get方法时拿到的依然是明文。因此show属性解决的是“防偷窥”问题,而不是“数据加密”问题。
1.1 基本语法
在创建Entry时,可以直接传入show参数,也可以在后续使用config方法动态修改。最常见的做法是把show设为星号,也有人用圆点或其他符号。下面的例子展示了用户名框和密码框的对比创建方式。
import tkinter as tk
root = tk.Tk()
root.title('登录示例')
# 用户名输入框:不设置show,正常显示
user_label = tk.Label(root, text='用户名')
user_label.pack()
user_entry = tk.Entry(root)
user_entry.pack()
# 密码输入框:设置show为星号
pwd_label = tk.Label(root, text='密码')
pwd_label.pack()
pwd_entry = tk.Entry(root, show='*')
pwd_entry.pack()
root.mainloop()
上面这段代码运行后,用户名框会显示敲入的字母,而密码框里只会看到一连串的星号。两者在代码层面的唯一区别就是密码框多了一个show='*'。这种写法简单直观,是Tkinter登录界面最基础的防护手段。
1.2 show属性的取值规则
show参数接收的是一个字符串,但界面上始终只取该字符串的第一个字符作为替代符号。如果你写成show='***',实际效果和使用show='*'完全一样。若传入空字符串show='',则等同于不设置show,恢复明文显示。
有些开发者误以为show可以支持“每个字符不同样式”,或者以为它能像前端password框那样由系统决定圆点样式,其实在Tkinter中替代符是完全由你指定的单字符。如果需要圆点,可以设show='•'(注意是中间点字符),但这依赖于字体是否支持该符号的渲染。
二、动态切换显示与真实数据获取
实际项目中,用户常希望有个“显示密码”复选框,用来临时查看自己输的密码。这时就要在运行时动态修改Entry的show属性。配合tk.BooleanVar和checkbutton,可以很方便地实现切换。
2.1 显示密码开关实现
核心思路是:当复选框未选中时,密码框show='*';选中时,把show设为空字符串。下面的示例演示了这种交互。
import tkinter as tk
def toggle_pwd():
if show_var.get():
pwd_entry.config(show='')
else:
pwd_entry.config(show='*')
root = tk.Tk()
root.title('密码可见切换')
tk.Label(root, text='密码').pack()
pwd_entry = tk.Entry(root, show='*')
pwd_entry.pack()
show_var = tk.BooleanVar()
tk.Checkbutton(root, text='显示密码', variable=show_var, command=toggle_pwd).pack()
root.mainloop()
这个模式在桌面软件里非常普遍。需要注意的是,动态改show不会清空已输入内容,也不会改变get方法的返回值。用户哪怕中途切到明文,程序后台拿到的字符串依旧是原本输入的密码。
2.2 获取真实输入值
无论show怎么设置,调用Entry的get方法永远返回用户真正键入的文本。下面示范在按钮回调里读取账号密码。
import tkinter as tk
def do_login():
username = user_entry.get()
password = pwd_entry.get()
# 此处password为明文,应做后续安全处理
print('用户输入的用户名:', username)
print('用户输入的密码:', password)
root = tk.Tk()
tk.Label(root, text='用户名').pack()
user_entry = tk.Entry(root)
user_entry.pack()
tk.Label(root, text='密码').pack()
pwd_entry = tk.Entry(root, show='*')
pwd_entry.pack()
tk.Button(root, text='登录', command=do_login).pack()
root.mainloop()
从代码可以看出,show属性对get毫无影响。很多新手以为设了show之后get拿到的是星号,这是错误理解。也正因如此,开发者不能把show当成加密存储手段,它只是视觉遮挡。
三、常见误区与配合安全措施
只靠show属性做登录加密输入,容易让人产生“已经安全了”的错觉。我们需要明确它的能力边界,并在必要环节补充真正的安全机制。
3.1 误区:show等于加密
前面反复提到,show仅仅替换了控件的显示字符。如果程序把pwd_entry.get()得到的明文直接写进日志、用明文发到接口、或存进本地文本,密码依然会暴露。show防的是“旁边的人瞄到屏幕”,防不了“程序自身处理不当”。
另一个误区是试图用多个不同show来提升复杂度,比如根据长度换符号,这既没必要也增加维护成本。Tkinter设计show的初衷就是统一占位,不是做混淆算法。
3.2 与哈希和传输加密配合
在真实的登录流程里,密码框拿到明文后,前端应至少做本地哈希(如用hashlib算sha256)再提交,或者全程走https让传输层加密。如果是离线校验,本地比对时也尽量只存哈希值,不要存原密码。下面给出一个简单的哈希示例,说明show之外的处理。
import tkinter as tk
import hashlib
def check_login():
pwd = pwd_entry.get()
pwd_hash = hashlib.sha256(pwd.encode('utf-8')).hexdigest()
# 假设本地正确哈希为如下值
if pwd_hash == '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8':
print('密码正确')
else:
print('密码错误')
root = tk.Tk()
tk.Label(root, text='密码').pack()
pwd_entry = tk.Entry(root, show='*')
pwd_entry.pack()
tk.Button(root, text='校验', command=check_login).pack()
root.mainloop()
这样一来,界面用show挡住视线,业务层用哈希挡住明文泄露,两者职责清晰。若涉及网络,还应使用requests配合https地址(例如https://ipipp.com/api/login)提交,避免中间人获取原密码。
四、总结对比与选型建议
为了更直观地理解show属性的定位,我们用一张表来对比普通Entry和设置了show的Entry。
| 对比项 | 不设置show | 设置show='*' |
|---|---|---|
| 界面显示 | 用户输入原字符 | 统一显示星号 |
| get返回值 | 明文 | 明文 |
| 适用场景 | 用户名、搜索框 | 密码、密保答案 |
| 安全级别 | 无视觉防护 | 仅防窥屏 |
在Python GUI开发中,Tkinter的Entry.show是最轻量的密码遮挡方案,几乎零成本。但它必须和后端哈希、传输加密组合使用,才能构成基本可用的登录安全链条。对于更复杂的界面需求,也可以考虑ttk.Entry,其show用法与原生Entry一致,只是样式更现代。
当你下次写Python桌面登录窗时,记得先给密码Entry加上show属性,再回头检查get之后的数据处理逻辑,别让“看起来加密”代替了“真的加密”。
PythonGUITkinter_Entry_show修改时间:2026-08-12 01:51:39