Is there an alternative to JPasswordField?
When typing a passphrase like
yeast bulk seize is shows pain
everybody can hear tapping the space bar, so it seems logical to display the spaces in the password field, too. So I'd like something capable of showing
***** **** ***** ** ***** ****
instead of
******************************
This would make typing easier while hardly decreasing the security.
UPDATE
Think twice before you update Riduidel's comment. When Bruce Schneier writes "It's time to show most passwords in clear text", then showing a small part of it must be correct, too. Especially showing a part which may get captured simply by listening.
Solution 1:
Here's a variation that uses setEchoChar()
to make the password visible for a predefined time: three seconds for example.
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 http://stackoverflow.com/questions/5339702 */
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);
}
}
Solution 2:
Was thinking JPasswordField
was simply a JTextField
simply overriding the renderer component, but it seems not to be the case.
So, instead of changing the renderer (like it would be the case if JTextField
had such a component), you'll have to use a JTextField
with a custom Document
holding two strings :
- Password text as written by user
- Displayed password
You'll have to make sure all Document
modifying methods change the password text, while all rendering methods use the displayed one.