How to mask a password from console input? I'm using Java 6.
I've tried using console.readPassword(), but it wouldn't work. A full example might help me actually.
Here's my code:
import java.io.BufferedReader;
import java.io.Console;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test
{
public static void main(String[] args)
{
Console console = System.console();
console.printf("Please enter your username: ");
String username = console.readLine();
console.printf(username + "\n");
console.printf("Please enter your password: ");
char[] passwordChars = console.readPassword();
String passwordString = new String(passwordChars);
console.printf(passwordString + "\n");
}
}
I'm getting a NullPointerException...
A full example ?. Run this code : (NB: This example is best run in the console and not from within an IDE, since the System.console() method might return null in that case.)
import java.io.Console;
public class Main {
public void passwordExample() {
Console console = System.console();
if (console == null) {
System.out.println("Couldn't get Console instance");
System.exit(0);
}
console.printf("Testing password%n");
char[] passwordArray = console.readPassword("Enter your secret password: ");
console.printf("Password entered was: %s%n", new String(passwordArray));
}
public static void main(String[] args) {
new Main().passwordExample();
}
}
You would use the Console class
char[] password = console.readPassword("Enter password");
Arrays.fill(password, ' ');
By executing readPassword echoing is disabled. Also after the password is validated it is best to overwrite any values in the array.
If you run this from an ide it will fail, please see this explanation for a thorough answer: Explained
Console console = System.console();
String username = console.readLine("Username: ");
char[] password = console.readPassword("Password: ");
If you're dealing with a Java character array (such as password characters that you read from the console), you can convert it to a JRuby string with the following Ruby code:
# GIST: "pw_from_console.rb" under "https://gist.github.com/drhuffman12"
jconsole = Java::java.lang.System.console()
password = jconsole.readPassword()
ruby_string = ''
password.to_a.each {|c| ruby_string << c.chr}
# .. do something with 'password' variable ..
puts "password_chars: #{password_chars.inspect}"
puts "password_string: #{password_string}"
See also "https://stackoverflow.com/a/27628738/4390019" and "https://stackoverflow.com/a/27628756/4390019"
The given code given will work absolutely fine if we run from console. and there is no package name in the class
You have to make sure where you have your ".class" file. because, if package name is given for the class, you have to make sure to keep the ".class" file inside the specified folder. For example, my package name is "src.main.code" , I have to create a code folder,inside main folder, inside src folder and put Test.class in code folder. then it will work perfectly.
Related
I have two strings representing a user and a password for that user. I'd like to check if this is a valid authentication pair in a Unix environment.
I thought about running a sudo bash command to authenticate inside Java code and see if the exit value of the command executed is equal to 0.
However I cannot make this work.
public class Test{
public static void main(String args[]){
String user = "user";
String pass = "pass\n";
try{
Process proc = new ProcessBuilder(
"/bin/sh","-c","sudo","-S","su",user).start();
OutputStream os = proc.getOutputStream();
os.write(pass.getBytes());
os.flush();
os.close();
try{
System.out.println(proc.waitFor());
} catch ( InterruptedException e ){
e.printStackTrace();
}
} catch ( IOException e ){
e.printStackTrace();
}
}
}
This code prints 1 as exit code.
I have really tried everything I could and found on the net but I still have to figure out how to make this work properly.
Can anybody help me?
Thx
sudo asks for the password of the current user, that is, the user that started the java process, so it will not check against user's password.
Instead of "/bin/sh","-c","sudo","-S","su",user).start();try "/bin/sh","-c","su",user).start();. This will just attempt to switch to that user, and as such will ask for user's password.
Based on su.c source code I've wrote a simple java program that makes the user credentials verification using JNA. It must works on all Unix based distributions that have the libc and crypt libraries, bellow a code snippet:
public static void main(String[] args) {
final Scanner scanner = new Scanner(System.in);
System.out.println("type the user");
final String user = scanner.nextLine();
System.out.println("type password");
final String password = scanner.nextLine();
System.out.println("RESULT\n===========================================");
final SPassword passwd = CLibrary.INSTANCE.getspnam(user);
if(passwd == null){
throw new RuntimeException(String.valueOf(Native.getLastError()));
}
final String encrypted = Crypt.INSTANCE.crypt(password, passwd.sp_pwdp);
System.out.printf("matches=%b%n", encrypted.equals(passwd.sp_pwdp));
}
interface Crypt extends Library {
Crypt INSTANCE = Native.loadLibrary("crypt", Crypt.class);
String crypt(String key, String salt);
}
interface CLibrary extends Library {
CLibrary INSTANCE = Native.loadLibrary("c", CLibrary.class);
Password getpwnam(String username);
SPassword getspnam(String username);
}
Testing
git clone https://github.com/mageddo/java-native-examples.git &&\
cd java-native-examples && git checkout -f ef4eb3e &&\
./gradlew clean build fatjar &&\
sudo java -jar build/libs/java-native-examples-all-*.jar
out
type the user
elvis
type password
*********
RESULT
===========================================
matches=true
Obs: The drawback is this application must run as root or sudo user, I can't fix that yet, anyway I think it is possible once su command don't need, for security reasons(if it is a problem in your context) I suggest to isolate this functionality to a application then call it by REST, Soap, TCP, whatever. this way your current application will not need to run as root.
If you want you can replace crypt function by apache commons codec lib function that do the same thing.
Reference
Function to recover user credentials
Lib for encrypt password in Linux format
Background info:
I am a high school student who is currently learning Java and as so if my code has an obvious flaw in it/ I accidentally reinvent the wheel with the code, I apologize.
Recently I have been working on writing an esoteric language and decided that I wanted to write it as an interpreter that translates the code to Java and then ran the code. My first step towards this was an attempt to create a mini-program that compiled and ran a java program. Most of the code from that was scrounged from another article, which is the third or fourth article I've looked threw:
how to compile & run java program in another java program?
I used the code from the third answer on that thread and initially thought that it worked. Unfortunately, when I tried running the code using the filename of the class for the program to be compiled and run within itself, the program failed.
Here is the modified code:
/**
*Functions printLines, Run, and parts of main came from stacks overflow
*originaly but modifications have been made
*https://stackoverflow.com/questions/4842684/how-to-compile-run-java-program-in-another-java-program
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
public class JTest
{
private static void printLines(String name, InputStream ins) throws Exception
{
String line = null;
BufferedReader in = new BufferedReader(new InputStreamReader(ins));
while ((line = in.readLine()) != null)
{
//System.out.println(name + " " + line);
System.out.println(line);
}
}
private static int run(String command) throws Exception
{
System.out.println(command);//prints command
Process pro = Runtime.getRuntime().exec(command);
printLines(command, pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
// System.out.println(command + " exitValue() " + pro.exitValue());
return pro.exitValue();
}
public static void main(String args[])
{
System.out.println("Enter the name of the file you want to run: ");
Scanner cin = new Scanner(System.in);
String jFileName = cin.nextLine();
try
{
int k = run("javac " + jFileName + ".java");
if (k==0)
k=run("java " + jFileName);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
I also used another class:
public class Cout
{
public static void main(String args [])
{
System.out.println("Hello World");
}
}
In my initial test...
Output:
Enter the name of the file you want to run:
Input:
Cout
Output:
javac Cout.java
java Cout
Hello World
Here's what Happened when I tried to run JTest from JTest...
Output:
Enter the name of the file you want to run:
Input:
JTest
Output:
javac JTest.java
java JTest
Enter the name of the file you want to run:
Input:
Cout
After I entered this, nothing more was outputted onto the terminal window which leads to my main question:
Why didn't my code run the Cout class and how do I fix it? (Preferably in a way that makes my code compatible with both linux and windows) Or is there a resource someone could point me towards?
Your main issue is understanding input and output streams.
Every process has three standard streams: standard input, standard output and standard error.
When you normally run a program from a command shell, be it Windows CMD or Linux terminal/console, the standard input is attached to the terminal's input stream, and the standard output and error to the console output.
When you run a process from within Java, especially when you use Runtime.exec rather than use a ProcessBuilder, the standard streams are piped from and two the calling program.
What you type into your "front" program doesn't automatically go to the "back" program. The "back" program calls nextLine on a scanner on System.in. Its System.in is redirected to the "front" program through Process.getOutputStream(). It is waiting for something to come through from that pipe. But your "front" program doesn't write anything to that stream. The only streams it has taken care of are the standard output and standard error - the output from the "back" program which is input from the point of view of the "front" program.
So the "back" program will sit and wait and do nothing. And your "front" program at this stage is trying to read its output. It will not stop reading it until the "back" program terminates or closes its standard output. Which of course it doesn't do.
So the two processes are deadlocked. Each of them is waiting for something from the other process.
In fact, there is another possible problem with the way you handle your streams. For example, if the program has errors, those errors will be placed in the standard error stream. If the program terminates, good. But if not, you'll never get to reading the standard error, because you'll still be endlessly waiting for the "standard output" from that program, which may not exist at all.
A possible solution to all this is to have separate threads handling each of the streams.
One thread will need to read the console input ("front" program System.in), and pass anything it reads to the getOutputStream() (standard input of "back" program).
One thread will need to read the "back" program's standard output (getInputStream()), and send everything to its own System.out.
One thread will need to do the same for the error stream and System.err.
But the complication is that when the "back" program terminates, you need to have those threads stop, so that you can read your own System.in again and run another command. The output-handling threads are relatively easy - when the process terminates, they will see "end of file" and they can terminate then. But the "input" reading thread will need to have a mechanism that interrupts it when the "back" program terminated.
BTW, if you use ProcessBuilder to build your process, you'll have better control of the redirection of your input and output. You could let your program write its output and error messages directly to console. You'll still need to design the input properly - lines that are intended for the "front" program should not be consumed by mistake by the "back" program, so you can't do without redirection for input.
It works for me under Fedora 23.
Here is my output:
$ java JTest
Enter the name of the file you want to run:
Cout
javac Cout.java
java Cout
Hello World
I have both JTest.java and Cout.java in the current directory when I run them.
After looking at the answers above, I realized that I forgot that I could call the main method to create a bit of a workaround. So while I will need to create a variable string at some point, here is the code along with its input and Output.
Class JTest
/**
*Functions printLines, Run, and parts of main came from stacks overflow
*originaly but modifications have been made
*http://stackoverflow.com/questions/4842684/how-to-compile-run-java-program-in-another-java-program
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
public class JTest
{
private static void printLines(String name, InputStream ins) throws Exception
{
String line = null;
BufferedReader in = new BufferedReader(new InputStreamReader(ins));
while ((line = in.readLine()) != null)
{
System.out.println(line);
}
}
private static int run(String command) throws Exception
{
Process pro = Runtime.getRuntime().exec(command);
printLines(command, pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
return pro.exitValue();
}
public static void main(String args[])
{
System.out.println("Enter the name of the file you want to run: ");
Scanner cin = new Scanner(System.in);
String jFileName = cin.nextLine();
try
{
String arg[] = { "" } ;
int binary = cin.nextInt();
int k = run("javac " + jFileName + ".java");
if (k == 0)
if (binary == 1)
JTest.main(arg);
else
Foo.main(arg);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Class Foo
import java.util.Scanner;
public class Foo
{
public static void main(String args [])
{
Scanner cin = new Scanner(System.in);
int bar = cin.nextInt();
System.out.println("Your number times 2 is: " + (bar * 2));
}
}
Input Output Dialogue
Output:
Enter the name of the file you want to run:
Input:
JTest
1
Output:
Enter the name of the file you want to run:
Input:
JTest
1
Output:
Enter the name of the file you want to run:
Input
Foo
0
4
Output:
Your number times 2 is: 4
As the program demonstrates, both input and output work fine.
This CSV reader which also checks the validity of an email address and password through the use of the map tool.
import java.io.*;
import java.util.*;
public class CSVReaders{
public static void run(String[] args) throws Exception {
Map<String, String> emailPasswordMap = new HashMap<String, String> ();
BufferedReader CSVFile =
new BufferedReader(new FileReader("testa453.csv"));
String dataRow = CSVFile.readLine();
while (dataRow != null){
String[] dataArray = dataRow.split(",");
emailPasswordMap.put (dataArray[0], dataArray[1]);
dataRow = CSVFile.readLine();
}
CSVFile.close();
//Scanner in = new Scanner(System.in);
//String email = in.nextLine();
//String password = in.nextLine();
String password = ("raj45");
String email = ("rakhter#bluebell.org");
if (password.equals (emailPasswordMap.get (email))) {
System.out.println ("The entered email and password are valid");
}
else {
System.out.println ("The entered email and password are invalid");
}
}
}
The problem which I am getting is that upon runing when i change the '//' over to the string password and email and attempt to use the scanner which I have included the program 'runs' but console window does not appear and I have to force stop the program to stop it running. Whilst using it as I have shown here it works perfectly. Previously I had an error with the scanner that related to static and non-static variables. I have looked them up and attempted to use instance variables but to little success.
Is the way in which I have declared the scanner wrong or can I not use Mapping in conjuction with the scanner?
EDIT: I am currently using BlueJ on Mac since I am reasonably new to java programming. And yes it does work as I have quoted it, it only stops working when I try to use the scanner.
Is the way in which I have declared the scanner wrong or can I not use Mapping in conjuction with the scanner?
The Scanner declaration appears to be correct. No, there is no restriction prohibiting the simultaneous use of any two parts of the Java standard library. So it is perfectly okay to use Map and Scanner together.
At current, the SO community's best guess is that you are using an IDE (like eclipse) that has a built-in console window/view. Under this assumption, it is assumed that you expect a black terminal/cmd window to open, however in most IDEs this is not the case. In eclipse the "console view" is where you will do your input. In Netbeans this will be the output window.
import java.io.*;
public class ConsoleDemo {
public static void main(String[] args) {
String str;
Console con;
con = System.console();
if (con == null)
return;
str = con.readLine("Enter a string : ");
con.printf("Here is your string %s", str);
}
}
I copied this code from the book, which says that I would get a prompt on the screen for entering a string, but my IDE just gives the message that the execution has termination, without giving me a prompt.
Eclipse nor Netbeans supports the use of Console. The Console.istty() method will return false and you will not have a console to use.
You can change your code to the following and achieve the same result and be able to run it from within the IDE.
import java.io.*;
public class ConsoleDemo {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter a String and press enter");
System.out.println("You entered the String: " + scan.nextLine()
}
}
What IDE are you using? This code works just fine when you run it from the command line, so the problem clearly lies with the configuration of your IDE.
Use the following commands to compile and run your code from the command line:
javac ConsoleDemo.java
java ConsoleDemo
Edit: as this link suggests, using System.Console doesn't always work in IDEs. Alternatively you can just use System.in.
Your code is working from both Eclipse and Command Prompt.
Try this way as well if you are using Java 5 or +
Scanner in = new Scanner(System.in);
System.out.print("Enter a String : ");
String string = in.nextLine();
System.out.println("Here is your String : " + string);
By default, eclipse does not associate console with the JVM. You may have to configure it. But if you run it in command line, it will have console definitely and hence it will run without any problem.
It is because your IDE runs this code by javaw.exe (windowless -> no console) not java.exe (with console window) command, so System.console() returns null.
Standard solution is to read data from input stream which is represented by System.in so you can use for instance Scanner like
Scanner keybord = new Scanner(System.in);
String line = keybord.readLine();
I am trying to implement the Java 6 console api. If I am trying to run my java class as Java Application why is my console null? Or shall I be running my .java from command promt like c:workspace>java -cp . console
My console.java class
public class console{
public static void main(String s[])throws IOException
{
Console c=System.console();
if(c==null)
{
System.err.println("Console object is not available");
}
else{
String name = null;
name = c.readLine("Enter any String: ");
...}
Please see this bug. Seems like you'd need to use the command line.