Почему делает JPasswordField.getPassword (), создают Строку с паролем в нем?

На некоторых клавиатурах вы должны поставить дополнительные тесты для символов '\ n' и '\ r'.

if(event.getCode().equals(KeyCode.ENTER) || event.getCharacter().getBytes()[0] == '\n' || event.getCharacter().getBytes()[0] == '\r') {
        // your action
    }
27
задан Tom Hawtin - tackline 11 June 2009 в 22:44
поделиться

4 ответа

На самом деле, вот реализация 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;
}

Единственный getText , в котором есть вызов getText ( int offset, int length, Segment txt) , который вызывает getChars (int where, int len, Segment txt) , который, в свою очередь, копирует символы непосредственно в сегмент Segment . буфер. Там не создаются Strings .

Затем буфер Segment копируется в возвращаемое значение и обнуляется перед возвратом метода.

Другими словами. : Нигде не висит лишняя копия пароля . Это совершенно безопасно, если вы используете его по назначению.

23
ответ дан 28 November 2019 в 04:33
поделиться

Реализация Swing слишком сложна для проверки вручную. Вам нужны тесты.

public class Pwd {
    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new javax.swing.JFrame("Pwd") {{
                    add(new javax.swing.JPasswordField() {
                        @Override public String getText() {
                            System.err.println("Awoooga!!");
                            return super.getText();
                        }
                        {
                            addActionListener(
                                new java.awt.event.ActionListener() {
                                    public void actionPerformed(
                                        java.awt.event.ActionEvent event
                                    ) {
                                        // Nice.
                                    }
                                }
                            );
                        }
                    });
                    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
                    pack();
                    setVisible(true);
                }};
            }
        });
    }
}

Мне кажется, это командная строка для (бессмысленного) события действия.

4
ответ дан 28 November 2019 в 04:33
поделиться

Ладно, плохо ... Все колокола зазвонили, как только я увидел вызов getText (), не замечая, что он был фактически введен мной с помощью слушателя действий, вот трассировка стека

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

Вот используемый код:

 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();
        }
    }

А вот вывод консоли:

Awhooa: secret
secret

И для фактического вызова getPassword (), возможно, я что-то упускаю, но где обнулен буфер сегмента? Я вижу копию массива, но не обнуление. Возвращенный массив будет обнулен мной, но массив сегментов все еще там ...

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));
    }
}

И вывод:

Before zeroing: [a, b, c] [a, b, c]
After zeroing: [?, ?, ?] [a, b, c]

(я поставил там вопросительные знаки, потому что не могу пропустить непечатаемые символы)

-M

5
ответ дан 28 November 2019 в 04:33
поделиться

** Я столкнулся с этим, когда искал способ фактически отображать некоторые конфиденциальные данные в компоненте Swing без использования объекта String. Очевидно, нет способа сделать это, если я не захочу переписать часть (все?) Swing API ... этого не произойдет.

Вы можете указать JPasswordField отображать символы, вызвав field.setEchoChar ('\ 0') . Это сохраняет остальную защиту, предлагаемую JPasswordField (без String s, без вырезания / копирования).

2
ответ дан 28 November 2019 в 04:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: