You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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事件),若控件为动态创建,在创建完成后立即执行即可。

二、视觉混淆:点击时激活多个字符

通过同时高亮多个无关按键干扰窥视者,具体实现步骤如下:

  1. 预先保存所有按键的默认外观状态;
  2. 给所有按键绑定统一的鼠标点击事件处理函数;
  3. 点击时随机选取多个无关按键与真实按键一起高亮,延迟后恢复默认状态。

示例代码:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 00:53:30