【问题标题】:How to cut/copy text in JPasswordField as char array? [closed]如何将 JPasswordField 中的文本剪切/复制为 char 数组? [关闭]
【发布时间】:2013-07-17 17:36:32
【问题描述】:

如何使用非字符串 APIJPasswordField 中的密码剪切/复制到剪贴板。从而关闭一个窗口让黑客查看密码。

根据此链接https://stackoverflow.com/a/8885343/2534090 char 数组与文本不同。

public static void main(String[] args) {
    Object pw = "Password";
    System.out.println("String: " + pw);

    pw = "Password".toCharArray();
    System.out.println("Array: " + pw);
}

打印:

String: Password
Array: [C@5829428e

我想要在剪贴板中的是[C@5829428e,而不是Password

我尝试使用StringSelection 复制剪贴板中的内容,但它的构造函数采用了String,它是不可变且不安全的。

【问题讨论】:

  • 阅读您的问题时,我真的很困惑。您想要获取 JPasswordField 的 char-Array 并且已经找到了此方法。你到底想用密码做什么?
  • 这可能会给你一些提示:stackoverflow.com/questions/17706393/…
  • 查看当你打印 char 数组时,你会得到不同的输出,当你打印 getText() 时,你会得到文本(即密码)。现在我的问题是如何将不同的输出放入剪贴板!
  • 当你打印char数组时如何? char 数组包含密码,就像字符串一样。
  • @EJP 看到这个链接stackoverflow.com/a/8885343/2534090

标签: java swing jpasswordfield


【解决方案1】:

您可以使用自定义 TransferHandler 来执行此操作。

根据 Using and Creating a Data Flavor 上的 Swing 教程部分,您应该能够使用 char[] 作为写入剪贴板的对象。

但是,我无法让它工作,最终将 StringBuilder 写入剪贴板。如果我尝试使用 char[],我注释掉了代码,也许其他人可以弄清楚我做错了什么。

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import java.io.*;

public class PasswordHandler extends TransferHandler
{
//  public final static DataFlavor CHAR_ARRAY_FLAVOR = new DataFlavor(char[].class, "Char Array");
    public final static DataFlavor CHAR_ARRAY_FLAVOR = new DataFlavor(StringBuilder.class, "StringBuilder");

    @Override
    public int getSourceActions(JComponent c)
    {
        return COPY;
    }

    @Override
    public Transferable createTransferable(final JComponent c)
    {
        return new Transferable()
        {
            @Override
            public Object getTransferData(DataFlavor flavor)
            {
                JPasswordField textField = (JPasswordField)c;
//              return textField.getPassword();
                return new StringBuilder( textField.getText() );
            }

            @Override
            public DataFlavor[] getTransferDataFlavors()
            {
                DataFlavor[] flavors = new DataFlavor[1];
                flavors[0] = CHAR_ARRAY_FLAVOR;
                return flavors;
            }

            @Override
            public boolean isDataFlavorSupported(DataFlavor flavor)
            {
                return flavor.equals(CHAR_ARRAY_FLAVOR);
            }
        };
    }

    @Override
    public boolean canImport(TransferSupport support)
    {
        boolean canImport = support.isDataFlavorSupported(CHAR_ARRAY_FLAVOR);
        return canImport;
    }

    @Override
    public boolean importData(TransferSupport support)
    {
//      char[] password;
        StringBuilder password;

        try
        {
//          password = (char[])support.getTransferable().getTransferData(CHAR_ARRAY_FLAVOR);
            password = (StringBuilder)support.getTransferable().getTransferData(CHAR_ARRAY_FLAVOR);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return false;
        }

        JPasswordField textField = (JPasswordField)support.getComponent();
        textField.setText(password.toString());
        return true;
    }

    private static void createAndShowUI()
    {
        JPasswordField tf1 = new JPasswordField(10);
        JPasswordField tf2 = new JPasswordField(10);

        TransferHandler handler = new PasswordHandler();
        tf1.setTransferHandler( handler );
        tf2.setTransferHandler( handler );
        tf1.putClientProperty("JPasswordField.cutCopyAllowed",true);
        tf2.putClientProperty("JPasswordField.cutCopyAllowed",true);

        JFrame frame = new JFrame("Password Copy");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(tf1, BorderLayout.WEST);
        frame.add(tf2, BorderLayout.EAST);
        frame.add(new JTextField(), BorderLayout.SOUTH);
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

代码从密码字段中获取整个文本。如果您只想要选定的字符,那么您需要修改getTransferData() 方法以仅将选定的字符添加到 StringBuilder。

【讨论】:

    猜你喜欢
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多