有没有JPasswordField的替代品?

3
输入密码短语时,例如:
yeast bulk seize is shows pain

每个人都可以听到敲击空格键的声音,因此在密码字段中显示空格似乎是合理的。所以我想要一个能够显示空格的东西。
***** **** ***** ** ***** ****

替代

******************************

这将使打字更容易,几乎不会降低安全性。

更新

在更新 Riduidel 的评论之前三思。当 布鲁斯·施奈尔 写道 "是时候明文显示大部分密码了",那么显示一小部分也一定是正确的。特别是显示可能通过简单监听就能获取到的部分。


13
“hardly”? 我的脚!由于使用习惯,存在空格字符可以显著提高密码质量。揭示这个字符(它会大大增加搜索空间,因此增加破解密码所需的时间)实际上会显著降低安全性。 - Riduidel
4
  1. 空格只是另一个字符。
  2. 谁说密码屏蔽实际上更安全
  3. 能听到你敲击空格键声音的人不是那些想要窃取你密码的人。
- Matt Ball
1
从我的角度来看,这绝对不值得努力。实际上,我完全看不到其中的任何附加价值。但当然,这是你的选择。 - Jan Zyka
2
@Matt:我以前阅读过那篇文章,我认为那是一种相当狭隘的观点。如果你不同意,考虑一下在连接到投影仪、房间里有50个人的情况下输入你的密码。现在他们即使不想窃取你的密码,他们也知道了它,而且甚至不需要特意寻找。很抱歉,但我不完全信任每个人。我绝对会讨厌一个连遮蔽选项都没有的产品。我个人喜欢大多数无线局域网密码输入方式,允许你关闭遮蔽。 - Mark Peters
@Mark:我同意尼尔森的观点是狭隘的(它完全关乎可用性),我也同意一个相当不错的解决方案是允许切换密码遮罩。尼尔森实际上提到了这一点:“因此,值得为他们提供一个复选框来遮蔽他们的密码。”我的主要观点是,迄今为止,最大的安全风险不是坐在隔壁办公桌上的迈克,他总是把头伸过隔板。 - Matt Ball
1
关于密码屏蔽,可以参考Bruce Schneier的观点。@Riduidel 如果有人能听到空格,为什么他们不能看到呢?如果有人像这样看到密码短语中的空格,他们可能会放弃(除非他们在为NSA工作:D)。 - maaartinus
2个回答

4

这是一种变体,使用setEchoChar()函数使密码在预定义的时间内可见:例如三秒钟。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPasswordField;
import javax.swing.Timer;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

/** @see https://dev59.com/olras4cB2Jgan1znsBJo */
public class PasswordTest {

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }

    private static void createAndShowGui() {
        JFrame jf = new JFrame("Test Password");
        JPasswordField jpwd = new JPasswordField();
        TimedPasswordListener tpl = new TimedPasswordListener(jpwd);
        jpwd.getDocument().addDocumentListener(tpl);
        jf.add(jpwd);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setLocationRelativeTo(null);
        jf.pack();
        jf.setVisible(true);
    }
}

class TimedPasswordListener implements DocumentListener, ActionListener {

    private Timer timer = new Timer(3000, this);
    private char echoChar;
    private JPasswordField pwf;

    public TimedPasswordListener(JPasswordField jp) {
        pwf = jp;
        timer.setRepeats(false);
    }

    public void insertUpdate(DocumentEvent e) {
        showText(e);
    }

    public void removeUpdate(DocumentEvent e) {
        showText(e);
    }

    public void changedUpdate(DocumentEvent e) {}

    public void showText(DocumentEvent e) {
        if (0 != pwf.getEchoChar()) {
            echoChar = pwf.getEchoChar();
        }
        pwf.setEchoChar((char) 0);
        timer.restart();
    }

    public void actionPerformed(ActionEvent e) {
        pwf.setEchoChar(echoChar);
    }
}

NB:此方法不涉及本问题中提出的其他合法安全问题。特别是,它可能会在内存中保留明文内容一段不确定的时间。 - trashgod
@maaartinus: 好观点。这种方法无法在其范围之外“改进”安全性;但据我所知,它也不会使其变得“更糟”。更多信息请参考此处 - trashgod

4

我认为 JPasswordField 只是一个覆盖了渲染器组件的JTextField,但事实并非如此。

因此,您需要使用带有自定义DocumentJTextField来保存两个字符串:

  1. 用户输入的密码文本
  2. 显示的密码

您需要确保所有修改Document的方法都更改密码文本,而所有渲染方法都使用显示的密码。


3
有许多不同的东西,尤其是JPasswordField不会为密码创建任何字符串,而是使用char[]。 这对安全性非常重要,因为您可以清除char[]但无法清除String。 - maaartinus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接