1

I have a basic text based Java app. I want the user to be able to enter sensitive info (password) in a text editing session that only exists for that purpose.

A bit like with git you get a temporary session/file in vi (or another set editor) to edit comment and save/quit - then the git process resumes and consumes that file. The file is (probably) deleted or at least forgotten about.

Do not need any advanced editor capabilities, just basic typing, backspace etc.

I want the user to be able to see what they're typing BUT once they have typed a password, it must be erased from screen. So plain STDIN won't work as the input remains on the screen.

How can I do it in Java or for that matter in another language? I have looked at Scanner (basically STDIN) and Console.readPassword (user cannot see what they type).

Perhaps a solution that involves STDIN and immediate erasure of the typed line could be acceptable. But emulating git/vi interplay is more attractive because it's arguably a bit more standard.

EDIT: I have implemented something close - create temp file and run notepad.exe on that, let user save and close notepad, read from temp file, delete it. Simple but it relies on an external tool, needs to be adjusted to run on linux as well.. I would like something more seamless where the behaviour is emulated within the java app itself

  • And using an external text editor produces a file with a password, which is not secure. Even deleting it doesn't help much. – NomadMaker May 13 '20 at 07:12
  • 1
    You can not reliably clear something what appeared on the standard output, conceptually it could be a printer, see https://en.m.wikipedia.org/wiki/Computer_terminal#Dumb_terminals – tevemadar May 13 '20 at 14:15
  • tevemadar - interesting.. fair point, although I am happy with the assumption it's a normal terminal with support for backspace, clear line etc | NomadMaker - yes, point taken – almondandapricot May 14 '20 at 05:47
  • On Linux it would be normal to run the command pointed to by the `$EDITOR` or `$VISUAL` environment variables to get an editor. However to take password input, the normal approach is to not print anything (even asterisks) to the terminal as the user types, so `Console.readPassword` sounds like the correct approach. – GKFX May 16 '20 at 10:12
  • If notepad is not acceptable because of being an external tool, how about a swing window? – matt May 16 '20 at 10:14

1 Answers1

1

Swing is pretty consistently available, here is an example of a method that opens a window, waits until the window is closed, and returns the text.

import javax.swing.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.awt.EventQueue;
import java.awt.event.*;

public class EditMe{
    LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>(1);
    public void showEditor(){
        JFrame frame = new JFrame("edit text");
        JEditorPane pane = new JEditorPane("txt", "");
        frame.add(pane);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.addWindowListener( new WindowAdapter(){
            @Override
            public void windowClosed(WindowEvent evt){
                try{
                    queue.put(pane.getText());
                    } catch(InterruptedException e){
                        //not really possible, but just incase.
                        throw new RuntimeException(e);
                    }
            }
        } ); 
        frame.setSize( 640, 480 );
        frame.setVisible(true);
    }

    public static String getText() throws InterruptedException{
        EditMe me = new EditMe();
        EventQueue.invokeLater( ()-> me.showEditor() );
        return me.queue.take();
    }

    public static void main(String[] args) throws Exception{
        System.out.println("waiting for response");
        String s = getText();
        System.out.println("response received: \n" + s);
    }

}

This would be about equivalent to a notepad solution, but it uses swing that comes with standard jdk's. (There are headless jdk's that don't include swing.)

matt
  • 10,892
  • 3
  • 22
  • 34