27 java security passwords swing
Swing的JPasswordField
有getPassword()
一个返回字符数组的方法.我对此的理解是,数组可以在使用后立即归零,这样你就不会在内存中长时间存在敏感的东西.检索密码的旧方法是使用getText()
,它返回一个String对象,但它已被弃用.
所以,我的问题是为什么Java在检索过程中实际使用它getPassword()
?为了更清楚,我正在调试我的测试应用程序的其他东西**,我跟着调用和爆炸... getText()
在JPasswordField
被调用,当然,一个很好的String对象与我的密码已经创建,现在挂在内存.
亲自尝试一下:
public class PasswordTest() {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPasswordField passField = new JPasswordField();
pass.addActionListener(new ActionListener() {
public ActionPerformed(ActionEvent evt) {
char[] p = passField.getPassword(); // put breakpoint
// do something with the array
}
});
frame.add(passField);
frame.setVisible(true);
frame.pack();
}
}
Run Code Online (Sandbox Code Playgroud)
跟进问题:这种"隐藏"的getText()
危险用途是什么?当然,如果一个专门的攻击者破坏了系统,它会获得你的密码,我说的是一个不那么专注的密码;)
**我在寻找一种在不使用String
对象的情况下在Swing组件上实际显示一些敏感数据的方法时遇到了这个问题.显然除非我愿意重写Swing API的部分(全部?),否则无法做到这一点.不会发生.
Ali*_*oud 38
这对我有用,可以帮助您构建一个Stringified密码:
String passText = new String(passField.getPassword());
Run Code Online (Sandbox Code Playgroud)
Mic*_*ers 23
实际上,这是Sun的实现getPassword()
:
public char[] getPassword() {
Document doc = getDocument();
Segment txt = new Segment();
try {
doc.getText(0, doc.getLength(), txt); // use the non-String API
} catch (BadLocationException e) {
return null;
}
char[] retValue = new char[txt.count];
System.arraycopy(txt.array, txt.offset, retValue, 0, txt.count);
return retValue;
}
Run Code Online (Sandbox Code Playgroud)
唯一getText
有一个调用getText(int offset, int length, Segment txt)
,调用getChars(int where, int len, Segment txt)
,然后将字符直接复制到Segment
缓冲区.那里没有Strings
被创造.
然后,将Segment
缓冲区复制到返回值中,并在方法返回之前将其清零.
换句话说:密码没有任何额外的副本.只要您按照指示使用它,它就是完全安全的.
小智 5
好吧,我的不好......我看到对getText()的调用时,所有的铃声都开始振铃,但没有注意到它实际上是我用Action侦听器引入的,这里是一个堆栈跟踪
PasswordTest$1.getText() line: 14
PasswordTest$1(JTextField).fireActionPerformed() line: not available
PasswordTest$1(JTextField).postActionEvent() line: not available
JTextField$NotifyAction.actionPerformed(ActionEvent) line: not available
SwingUtilities.notifyAction(Action, KeyStroke, KeyEvent, Object, int) line: not available
Run Code Online (Sandbox Code Playgroud)
这是使用的代码:
import java.awt.event.*;
import javax.swing.*;
public class PasswordTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPasswordField passField = new JPasswordField() {
@Override
public String getText() {
System.err.println("Awhooa: " + super.getText()); //breakpoint
return null;
}
};
passField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
char[] p = passField.getPassword();
System.out.println(p);
}
});
frame.add(passField);
frame.setVisible(true);
frame.pack();
}
}
Run Code Online (Sandbox Code Playgroud)
这是控制台输出:
Awhooa: secret
secret
Run Code Online (Sandbox Code Playgroud)
对于getPassword()的实际调用,也许我错过了什么,但是Segment的缓冲区在哪里归零?我看到一个数组副本,但不是归零.返回的数组将由我自己归零,但Segment的数组仍在那里......
import java.util.Arrays;
public class ZeroingTest {
public static void main(String[] args) {
char[] a = {'a','b','c'};
char[] b = new char[a.length];
System.arraycopy(a, 0, b, 0, b.length);
System.out.println("Before zeroing: " + Arrays.toString(a) + " " + Arrays.toString(b));
Arrays.fill(a, '\0');
System.out.println("After zeroing: " + Arrays.toString(a) + " " + Arrays.toString(b));
}
}
Run Code Online (Sandbox Code Playgroud)
并输出:
Before zeroing: [a, b, c] [a, b, c]
After zeroing: [?, ?, ?] [a, b, c]
Run Code Online (Sandbox Code Playgroud)
(我在那里放了问号,因为我无法通过不可打印的字符)
-M
归档时间: |
|
查看次数: |
86987 次 |
最近记录: |