如何在Delphi的TTouchKeyboard上安全输入密码防止他人窥视?
Delphi TTouchKeyboard 密码输入安全问题解决方案
一、不修改源码禁用OnMouseDown事件
如果要消除按键点击时的视觉反馈,可直接遍历TTouchKeyboard的所有子按键控件,清空或替换它们的OnMouseDown事件绑定:
procedure DisableTouchKeyboardKeyFeedback(TouchKeyboard: TTouchKeyboard); var I: Integer; begin for I := 0 to TouchKeyboard.ComponentCount - 1 do begin if TouchKeyboard.Components[I] is TCustomButton then begin // 清空MouseDown事件,消除点击时的高亮反馈 TCustomButton(TouchKeyboard.Components[I]).OnMouseDown := nil; // 若需保留输入功能,可替换为仅处理输入逻辑的自定义事件 end; end; end;
建议在TTouchKeyboard显示前调用该方法(比如表单OnShow事件),若控件为动态创建,在创建完成后立即执行即可。
二、视觉混淆:点击时激活多个字符
通过同时高亮多个无关按键干扰窥视者,具体实现步骤如下:
- 预先保存所有按键的默认外观状态;
- 给所有按键绑定统一的鼠标点击事件处理函数;
- 点击时随机选取多个无关按键与真实按键一起高亮,延迟后恢复默认状态。
示例代码:
type TForm1 = class(TForm) TouchKeyboard1: TTouchKeyboard; PasswordEdit: TEdit; procedure FormCreate(Sender: TObject); private FButtonDefaults: array of TColor; FAllButtons: array of TCustomButton; procedure ButtonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure SaveButtonDefaultStates; public end; procedure TForm1.SaveButtonDefaultStates; var I: Integer; begin SetLength(FAllButtons, TouchKeyboard1.ComponentCount); SetLength(FButtonDefaults, TouchKeyboard1.ComponentCount); for I := 0 to TouchKeyboard1.ComponentCount - 1 do begin if TouchKeyboard1.Components[I] is TCustomButton then begin FAllButtons[I] := TCustomButton(TouchKeyboard1.Components[I]); FButtonDefaults[I] := FAllButtons[I].Color; FAllButtons[I].OnMouseDown := ButtonMouseDown; end; end; end; procedure TForm1.ButtonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); const RandomBtnCount = 2; // 额外高亮的按键数量 var RealButton: TCustomButton; RandomIndices: array[0..RandomBtnCount-1] of Integer; I, RandIdx: Integer; begin RealButton := TCustomButton(Sender); Randomize; // 随机选取不重复的无关按键 for I := 0 to RandomBtnCount-1 do begin repeat RandIdx := Random(Length(FAllButtons)); until (FAllButtons[RandIdx] <> RealButton) and (FAllButtons[RandIdx] <> nil); RandomIndices[I] := RandIdx; end; // 高亮真实按键和随机选中的按键 RealButton.Color := clHighlight; for I := 0 to RandomBtnCount-1 do FAllButtons[RandomIndices[I]].Color := clHighlight; // 执行密码输入逻辑 PasswordEdit.Text := PasswordEdit.Text + RealButton.Caption; // 延迟恢复默认外观(避免同步阻塞UI) TThread.CreateAnonymousThread( procedure begin Sleep(200); // 高亮持续时间,可按需调整 TThread.Synchronize(nil, procedure var J: Integer; begin RealButton.Color := RealButton.DefaultColor; for J := 0 to RandomBtnCount-1 do FAllButtons[RandomIndices[J]].Color := FButtonDefaults[RandomIndices[J]]; end); end).Start; end; procedure TForm1.FormCreate(Sender: TObject); begin SaveButtonDefaultStates; // 可选:隐藏鼠标光标 ShowCursor(False); end;
三、额外安全优化
- 隐藏鼠标光标:密码输入阶段调用
ShowCursor(False),输入完成后用ShowCursor(True)恢复; - 随机布局键盘:每次弹出密码键盘时,动态打乱按键位置,避免固定位置被窥视者记忆;
- 严格掩码输入:确保密码输入框始终显示掩码字符(如
*),不泄露输入长度或字符类型。
内容的提问来源于stack exchange,提问作者Michael Hutter
相关产品推荐
相关产品推荐

