一尘不染

使用Linux Terminal运行命令的Java程序

linux

我的问题是,我正在通过终端运行一些adb命令。我写了一个工具;这将使事情变得容易。回到问题所在,为了使命令运行,我必须在终端上输入“密码”。那么,我该如何做才能使“密码”部分出现在JOptionPane.showInputDialog框上?

这是我到目前为止的内容:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;


public class flash implements ActionListener {
    private File runfile;
    @Override
    public void actionPerformed(ActionEvent arg0) {
        {


            JFileChooser adbflashfile = new JFileChooser("/home/local/ANT/arthm/Desktop/os"); 
           FileNameExtensionFilter filter = new FileNameExtensionFilter(".py", "py");

                adbflashfile.setFileFilter(filter);

            int returnVal = adbflashfile.showOpenDialog(null);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                runfile = adbflashfile.getSelectedFile();

                try {
                    Runtime.getRuntime().exec("sudo python ./flashimage.py");
                } catch (IOException e1) {

                    e1.printStackTrace();
                }
                //This is where a real application would open the file.
                System.out.println("File: " + runfile.getName() + ".");    
            } else {
                JOptionPane.showMessageDialog(null, "Open command cancelled by user.");
            }
            System.out.println(returnVal);
        }
    };
    }

阅读 314

收藏
2020-06-07

共1个答案

一尘不染

您可以“读取”过程输入,并在“检测到”密码提示时显示,JOptionPane并要求用户输入密码。

在开始该过程之前,您“可以”提示用户输入密码,因为您知道需要将其发送给该过程。

您可能仍然需要监视进程的输出,以确定何时需要发送密码。

让我们从…开始

Runtime.getRuntime().exec("sudo python ./flashimage.py");

您完全忽略了Process。您也不处理输出,但是您没有办法向流程提供输入…

通常,Runtime#exec充其量是有问题的。您最好使用ProcessBuilder....

// Build the command to be executed.  Note that each parameter becomes
// it's own argument, this deals with parameters that contain spaces
// much better then Runtime#exec alone...
ProcessBuilder pb = new ProcessBuilder("sudo", "python", "./flashimage.py");
pb.redirectError();

InputStream is = null;
try {
    Process p = pb.start();
    is = p.getInputStream();
    StringBuilder output = new StringBuilder(80);
    int in = -1;
    while ((in = is.read()) != -1) {
        if (in != '\n') {
            output.append((char)in);
            // You will need to define PASSWORD_PROMPT
            if (PASSWORD_PROMPT.equals(output.toString())) {
                String text = JOptionPane.showInputDialog("Password");
                OutputStream os = p.getOutputStream();
                os.write(text.getBytes());
            }
        } else {
            System.out.println(output.toString());
            output.delete(0, output.length());
        }
    }
} catch (IOException exp) {
    exp.printStackTrace();
} finally {
    try {
        is.close();
    } catch (Exception e) {
    }
}

现在,毫无疑问,有人会指出(至少)这种方法有两个问题……

  1. JOptionPane.showInputDialog("Password");将显示一个法线JTextField,不会隐藏密码字符和
  2. String 不是最安全的密码存储方式…

相反,我们应该使用JPasswordField并将结果char数组转换为byte数组…

JPasswordField password = new JPasswordField(10);
JLabel label = new JLabel("Password: ");
JPanel panel = new JPanel();
panel.add(label);
panel.add(password);

int option = JOptionPane.showConfirmDialog(null, panel, "Password", JOptionPane.OK_CANCEL_OPTION);
if (option == JOptionPane.OK_OPTION) {
    char[] userPassword = password.getPassword();
    byte[] bytes = new byte[userPassword.length * 2];
    for (int i = 0; i < userPassword.length; i++) {
        bytes[i * 2] = (byte) (userPassword[i] >> 8);
        bytes[i * 2 + 1] = (byte) userPassword[i];
    }
    os.write(bytes);
}
2020-06-07