I have a VB script to which I need to pass username and password.
I want to run this VB script through Java code programmatically.
Is there a way that I can pass the Windows credentials to the VB script in Java programmatically?
You can have the credentials on the OS environment and read them from there:
String credentials = System.getenv().get("encrypted_credentials_or_something");
And then run your command from Java. However, Runtime.exec() won't work in some cases:
When the command is not on the System's PATH
When arguments are involved
When you want to have access to the process output
When you need to be able to kill the process
When you need to check if it terminated successfully or in error (status code != 0 - which is why you write System.exit(int) to terminate a Java application. The System.exit(1), for example, indicates abnormal termination)
That's why I created this utility class to execute external processes with arguments and everything. It works very well for me:
import java.io.*;
import java.util.*;
public class ExternalCommandHelper {
public static final void executeProcess(File directory, String command) throws Exception {
InputStreamReader in = null;
try {
//creates a ProcessBuilder with the command and its arguments
ProcessBuilder builder = new ProcessBuilder(extractCommandWithArguments(command));
//errors will be printed to the standard output
builder.redirectErrorStream(true);
//directory from where the command will be executed
builder.directory(directory);
//starts the process
Process pid = builder.start();
//gets the process output so you can print it if you want
in = new InputStreamReader(pid.getInputStream());
//simply prints the output while the process is being executed
BufferedReader reader = new BufferedReader(in);
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int status = 0;
//waits for the process to finish. Expects status 0 no error. Throws exception if the status code is anything but 0.
if ((status = pid.waitFor()) != 0) {
throw new IllegalStateException("Error executing " + command + " in " + directory.getAbsolutePath() + ". Error code: " + status);
}
} finally {
if (in != null) {
in.close();
}
}
}
//Splits the command and arguments. A bit more reliable than using String.split()
private static String[] extractCommandWithArguments(String command) {
StringTokenizer st = new StringTokenizer(command);
String[] cmdWithArgs = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++) {
cmdWithArgs[i] = st.nextToken();
}
return cmdWithArgs;
}
}
I am working on application which doesn't have any login mechanism, any user in my organization can use that. But I want to pick the username of the remote users who will use my tool. I have a button clicking on that I want to get their usernames.
I tried request.getRemoteUser got null. tried System.getenv("USERNAME") getting the logged in user of the localhost where the server resides. Tried getHostName, System.getProperty got the localhost name. Tried this also - new com.sun.security.auth.module.NTSystem().getName() but same result.
I am using java6, windows server and glassfish3 server.
Please suggest something as I don't want to use any external link and tool.
You want to do something called SSO (Single Sign On): A user is logged in somewhere (in your case his Windows computer) and you want to authenticate the user with this (already done) login. This is a very common use case and there are different ways to do that. However, the big question is always how you can trust those third party system. And this is where the trouble begins.
Since your question is not very clear, I assume you have a Java Glassfish server running on Windows Server and a Java client (because you asked for Java code). So the Java server must authenticate who the user of the Java client is. And the server must trust this information.
Using System.getProperty("user.name"); isn't a good idea since anybody can change it. You can start your Java program with java -Duser.name=Joe <your_program> and that's it.
But since you are on Windows, you could use Windows to help you. If both, your client and server, are in the same domain, they are authenticated against the same system. You can ask this system for the user identity. Typically machines of a company are in the same domain.
To do this there is a tool called Waffle. It does a secure Windows authentication between machines in the same domain. If your client and server are in the same domain, it is an easy way to perform an SSO (a single sign on). You can find it on GitHub: http://dblock.github.io/waffle/
Here is a simple example from one of my own questions a couple of months ago (see here):
// client credentials handle
IWindowsCredentialsHandle credentials= WindowsCredentialsHandleImpl.getCurrent("Negotiate");
credentials.initialize();
// initial client security context
WindowsSecurityContextImpl clientContext = new WindowsSecurityContextImpl();
clientContext.setPrincipalName(Advapi32Util.getUserName());
clientContext.setCredentialsHandle(credentials.getHandle());
clientContext.setSecurityPackage(securityPackage);
clientContext.initialize();
// accept on the server
WindowsAuthProviderImpl provider = new WindowsAuthProviderImpl();
IWindowsSecurityContext serverContext = null;
do {
if (serverContext != null) {
// initialize on the client
SecBufferDesc continueToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, serverContext.getToken());
clientContext.initialize(clientContext.getHandle(), continueToken);
}
// accept the token on the server
serverContext = provider.acceptSecurityToken(clientContext.getToken(), "Negotiate");
} while (clientContext.getContinue() || serverContext.getContinue());
System.out.println(serverContext.getIdentity().getFqn());
for (IWindowsAccount group : serverContext.getIdentity().getGroups())
System.out.println(" " + group.getFqn());
You can use Waffle also for websites. However, I didn't do that and cannot explain you what to do in this case.
And one important remark: I think you are a little bit confused. If you do request.getRemoteHost() on your server, you try to get the identity of the client who send the request (by the way, it is not secure, a client could send anything). However, if you do System.getProperty("user.name") on your server, you try to get the name of the server itself. Be aware where you are (on client or server) and what you want. And make sure whether you can trust this information or not. Security is difficult.
java class code to find who loggedin into a remote computer in a domain
package com.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import com.test.Pubfun;
public class UserName {
public static HashMap <String,String> hmun=new HashMap<String, String>();
public String setUserFromIP(String arg1) {
String m = arg1;
StringBuilder user = new StringBuilder();
String u = "";
String user2 = null;
try {
Process p = Runtime.getRuntime().exec("query user /server:" + m);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line = reader.readLine();
while (line != null) {
line = reader.readLine();
user.append(line);
line=null;
}
} catch (IOException e1) {
} catch (InterruptedException e2) {
}
u = user.toString().replace("null", "");
try {
user2 = this.getUserFromString(u);
} catch (ArrayIndexOutOfBoundsException ae) {
}
u.replace("null", " ");
System.out.println(user2);
hmun.put("username",user2);
return user2;
}
public static String gethmun()
{
String t=hmun.get("username");
return t;
}
public String getUserFromString(String u) {
HashMap <String,String> hmun=new HashMap<String, String>();
String input = u;
int length, size;
length = input.length();
size = length ;
String strarray[] = new String[size];
strarray = input.split("\\s+");
for (int i = 0; i < strarray.length; i++) {
if(strarray[i].equals("Active")){
hmun.put("username", strarray[i-3]);
}
}
String user1=hmun.get("username");
return user1;
}
}
HttpServletRequest.getRemoteUser() might optionally return the login of user making the request (if authenticated), but it is not the username of the user logged in on the remote machine.
There is no way to query the username of the remote machine. Browsers or applications making the requests might send this info voluntarily, but if they don't, you won't find a way to get it. And by default they don't send it so don't count on this.
This gives you the current logged in Username from your local Windows System System.getProperty("user.name");
I am trying to run an scp command within Java. Here is my code,
try {
Process p = Runtime.getRuntime().exec("scp -P" + PORT + " " + FILEPATH + " " + USERNAME + "#" + HOST + ":somefolder/");
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
String line;
while ((line=br.readLine()) != null) {
System.out.println("LINE: " + line);
if (line.contains(USERNAME+"#"+HOST+"'s password:")) {
bw.write(PASSWORD);
bw.newLine();
}
}
System.out.println("end of while.");
} catch (IOException e) {
e.printStackTrace();
}
As you can see, I do not want to print the password blindly to the p.getOutputStream(), which is suggested in almost all similar questions. I want to read the prompt and act accordingly. For example, scp may prompt something like "The authenticity of host 'SOME HOST' can't be established...", which prompts for a yes/no. Or something else that I cannot imagine right now.
The problem with my code is that it never reads a line, although the scp prompts for password, which is seen on the cli. Any suggestion?
EDIT:
I changed the code to use ProcessBuilder, with String[] constructor, as Andrew Thompson suggested. Here is the complete code:
package scptest;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class STest {
// args => filepath, username, host, port, password
public static void main(String[] args) {
try {
ProcessBuilder pb = new ProcessBuilder("scp", "-P", args[3],
args[0], args[1] + "#" + args[2] + ":folder/");
Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(
p.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
p.getOutputStream()));
String line;
bw.write(args[4]);
bw.newLine();
bw.flush();
System.out.println("RETURN: " + p.waitFor());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
As you can see, I quitted checking the prompts of the scp, and sent the password directly to the input stream of Process. This does not work either! I mean, when I execute the jar file in the commad line, I see the prompt "username#host's password:", and it waits for the password. When I hit enter without entering the password, it just re-asks the password without any error message, which means no string is given to the input stream of the Process, i.e. My BufferedWriter seems doing nothing.
I am compiling my program on a w8 maching with jdk 1.7.0_45, where I run the program on an Ubuntu Server x64 with jre 1.7.0_51.
I found that its easier to configure the rsa files and use the -i option in the scp command.
Just use -i where is the private key of the HOST machine. You'll also need to add the public key from the machine running the command to the authorized keys file in the HOST machine.
That way he won't prompt you for a password a all. Furthermore if you use the -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null options you'll rarely have anything to worry about (which isn't always a good thing!)
I'm trying to create a web application which can display the results of a ping command real-time. I'm using JSP in the backend. I'm actually getting the result correctly. But the problem is, the result is not displayed in real-time. The application processes the ping command and dumps the result all at once. What I need is that, the application has to display the result line after line as and when a line of result is obtained.
Here is my code
String ip = request.getParameter("ipaddress");
String pingCmd = "ping -c 3 " + ip;
Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec(pingCmd);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
{
out.println(inputLine + "<br />");
}
in.close();
What is the change I need to make in this code.
Regards
Sunil Kumar B M
You can do this with a comet servlet. For tomcat 6: http://tomcat.apache.org/tomcat-6.0-doc/aio.html
How can I determine the IP of my router/gateway in Java? I can get my IP easily enough. I can get my internet IP using a service on a website. But how can I determine my gateway's IP?
This is somewhat easy in .NET if you know your way around. But how do you do it in Java?
On Windows, OSX, Linux, etc then Chris Bunch's answer can be much improved by using
netstat -rn
in place of a traceroute command.
Your gateway's IP address will appear in the second field of the line that starts either default or 0.0.0.0.
This gets around a number of problems with trying to use traceroute:
on Windows traceroute is actually tracert.exe, so there's no need for O/S dependencies in the code
it's a quick command to run - it gets information from the O/S, not from the network
traceroute is sometimes blocked by the network
The only downside is that it will be necessary to keep reading lines from the netstat output until the right line is found, since there'll be more than one line of output.
EDIT: The Default Gateway's IP Address is in the second field of the line that starts with 'default' if you are on a MAC (tested on Lion), or in the third field of the line that starts with '0.0.0.0' (tested on Windows 7)
Windows:
Network Destination Netmask Gateway Interface Metric
0.0.0.0 0.0.0.0 192.168.2.254 192.168.2.46 10
Mac:
Destination Gateway Flags Refs Use Netif Expire
default 192.168.2.254 UGSc 104 4 en1
Java doesn't make this as pleasant as other languages, unfortunately. Here's what I did:
import java.io.*;
import java.util.*;
public class ExecTest {
public static void main(String[] args) throws IOException {
Process result = Runtime.getRuntime().exec("traceroute -m 1 www.amazon.com");
BufferedReader output = new BufferedReader(new InputStreamReader(result.getInputStream()));
String thisLine = output.readLine();
StringTokenizer st = new StringTokenizer(thisLine);
st.nextToken();
String gateway = st.nextToken();
System.out.printf("The gateway is %s\n", gateway);
}
}
This presumes that the gateway is the second token and not the third. If it is, you need to add an extra st.nextToken(); to advance the tokenizer one more spot.
On windows parsing the output of IPConfig will get you the default gateway, without waiting for a trace.
try{
String gateway;
Process result = Runtime.getRuntime().exec("netstat -rn");
BufferedReader output = new BufferedReader(new InputStreamReader(result.getInputStream()));
String line = output.readLine();
while(line != null){
if ( line.trim().startsWith("default") == true || line.trim().startsWith("0.0.0.0") == true )
break;
line = output.readLine();
}
if(line==null) //gateway not found;
return;
StringTokenizer st = new StringTokenizer( line );
st.nextToken();
st.nextToken();
gateway = st.nextToken();
System.out.println("gateway is: "+gateway);
} catch( Exception e ) {
System.out.println( e.toString() );
gateway = new String();
adapter = new String();
}
You may be better off using something like checkmyip.org, which will determine your public IP address - not necessarily your first hop router: at Uni I have a "real" IP address, whereas at home it is my local router's public IP address.
You can parse the page that returns, or find another site that allows you to just get the IP address back as the only string.
(I'm meaning load this URL in Java/whatever, and then get the info you need).
This should be totally platform independent.
Regarding UPnP: be aware that not all routers support UPnP. And if they do it could be switched off (for security reasons). So your solution might not always work.
You should also have a look at NatPMP.
A simple library for UPnP can be found at http://miniupnp.free.fr/, though it's in C...
To overcome the issues mentioned with traceroute (ICMP-based, wide area hit) you could consider:
traceroute to your public IP (avoids wide-area hit, but still ICMP)
Use a non-ICMP utility like ifconfig/ipconfig (portability issues with this though).
What seems the best and most portable solution for now is to shell & parse netstat (see the code example here)
output of netstat -rn is locale specific.
on my system (locale=de) the output looks like:
...
Standardgateway: 10.22.0.1
so there is no line starting with 'default'.
so using netstat might be no good idea.
This Version connects to www.whatismyip.com, reads the content of the site and searches via regular expressions the ip adress and prints it to the cmd. Its a little improvement of MosheElishas Code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
BufferedReader buffer = null;
try {
URL url = new URL(
"http://www.whatismyip.com/tools/ip-address-lookup.asp");
InputStreamReader in = new InputStreamReader(url.openStream());
buffer = new BufferedReader(in);
String line = buffer.readLine();
Pattern pattern = Pattern
.compile("(.*)value=\"(\\d+).(\\d+).(\\d+).(\\d+)\"(.*)");
Matcher matcher;
while (line != null) {
matcher = pattern.matcher(line);
if (matcher.matches()) {
line = matcher.group(2) + "." + matcher.group(3) + "."
+ matcher.group(4) + "." + matcher.group(5);
System.out.println(line);
}
line = buffer.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (buffer != null) {
buffer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
BufferedReader buffer = null;
try {
URL url = new URL(
"http://www.whatismyip.com/tools/ip-address-lookup.asp");
InputStreamReader in = new InputStreamReader(url.openStream());
buffer = new BufferedReader(in);
String line = buffer.readLine();
Pattern pattern = Pattern
.compile("(.*)value=\"(\\d+).(\\d+).(\\d+).(\\d+)\"(.*)");
Matcher matcher;
while (line != null) {
matcher = pattern.matcher(line);
if (matcher.matches()) {
line = matcher.group(2) + "." + matcher.group(3) + "."
+ matcher.group(4) + "." + matcher.group(5);
System.out.println(line);
}
line = buffer.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (buffer != null) {
buffer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
That is not as easy as it sounds. Java is platform independent, so I am not sure how to do it in Java. I am guessing that .NET contacts some web site which reports it back. There are a couple ways to go. First, a deeper look into the ICMP protocol may give you the information you need. You can also trace the IP you go through (your route). When you encounter an IP that is not in the following ranges:
10.0.0.0 – 10.255.255.255
172.16.0.0 – 172.31.255.255
192.168.0.0 – 192.168.255.255
it is the IP one hop away from yours, and probably shares a few octets of information with your IP.
Best of luck. I'll be curious to hear a definitive answer to this question.
Try shelling out to traceroute if you have it.
'traceroute -m 1 www.amazon.com' will emit something like this:
traceroute to www.amazon.com (72.21.203.1), 1 hops max, 40 byte packets
1 10.0.1.1 (10.0.1.1) 0.694 ms 0.445 ms 0.398 ms
Parse the second line. Yes, it's ugly, but it'll get you going until someone posts something nicer.
Matthew: Yes, that is what I meant by "I can get my internet IP using a service on a website." Sorry about being glib.
Brian/Nick: Traceroute would be fine except for the fact that lots of these routers have ICMP disabled and thus it always stalls.
I think a combination of traceroute and uPnP will work out. That is what I was planning on doing, I as just hoping I was missing something obvious.
Thank you everyone for your comments, so it sounds like I'm not missing anything obvious. I have begun implementing some bits of uPnP in order to discover the gateway.
You can query the URL "http://whatismyip.com/automation/n09230945.asp".
For example:
BufferedReader buffer = null;
try {
URL url = new URL("http://whatismyip.com/automation/n09230945.asp");
InputStreamReader in = new InputStreamReader(url.openStream());
buffer = new BufferedReader(in);
String line = buffer.readLine();
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (buffer != null) {
buffer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
In windows you can just use the following command:
ipconfig | findstr /i "Gateway"
Which will give you output like:
Default Gateway . . . . . . . . . : 192.168.2.1
Default Gateway . . . . . . . . . : ::
However I can't run this command with Java, gonna post when I figure this out.
You can use netstat -rn command which is available on Windows, OSX, Linux, etc platform. Here is my code:
private String getDefaultAddress() {
String defaultAddress = "";
try {
Process result = Runtime.getRuntime().exec("netstat -rn");
BufferedReader output = new BufferedReader(new InputStreamReader(
result.getInputStream()));
String line = output.readLine();
while (line != null) {
if (line.contains("0.0.0.0")) {
StringTokenizer stringTokenizer = new StringTokenizer(line);
stringTokenizer.nextElement(); // first element is 0.0.0.0
stringTokenizer.nextElement(); // second element is 0.0.0.0
defaultAddress = (String) stringTokenizer.nextElement();
break;
}
line = output.readLine();
} // while
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return defaultAddress;
} // getDefaultAddress
I'm not sure if it works on every system but at least here I found this:
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Main
{
public static void main(String[] args)
{
try
{
//Variables to find out the Default Gateway IP(s)
String canonicalHostName = InetAddress.getLocalHost().getCanonicalHostName();
String hostName = InetAddress.getLocalHost().getHostName();
//"subtract" the hostName from the canonicalHostName, +1 due to the "." in there
String defaultGatewayLeftover = canonicalHostName.substring(hostName.length() + 1);
//Info printouts
System.out.println("Info:\nCanonical Host Name: " + canonicalHostName + "\nHost Name: " + hostName + "\nDefault Gateway Leftover: " + defaultGatewayLeftover + "\n");
System.out.println("Default Gateway Addresses:\n" + printAddresses(InetAddress.getAllByName(defaultGatewayLeftover)));
} catch (UnknownHostException e)
{
e.printStackTrace();
}
}
//simple combined string out of the address array
private static String printAddresses(InetAddress[] allByName)
{
if (allByName.length == 0)
{
return "";
} else
{
String str = "";
int i = 0;
while (i < allByName.length - 1)
{
str += allByName[i] + "\n";
i++;
}
return str + allByName[i];
}
}
}
For me this produces:
Info:
Canonical Host Name: PCK4D-PC.speedport.ip
Host Name: PCK4D-PC
Default Gateway Leftover: speedport.ip
Default Gateway Addresses:
speedport.ip/192.168.2.1
speedport.ip/fe80:0:0:0:0:0:0:1%12
I'd require more tests on other Systems/Configurations/PC-Gateway-Setups to confirm if it works everywhere. Kind of doubt it but this was the first I found.