I am creating a web services client in Java that is intended to extract data from a sharepoint site. My code works in the windows environment but not in the Linux environment. Research lead me to write a java.net.Authenticator implementation as described by the Java Documentation on HTTP Authentication. The link is provided below:
http://java.sun.com/javase/6/docs/technotes/guides/net/http-auth.html
I am using JDK 1.6.0_06. the Sharepoint server requires NTLMv2 Authentication. In windows the authenticator is not called my login credentials are automatically used. In Linux, the authenticator is called and fails. The Linux stack trace is:
java.io.IOException: Server returned HTTP response code: 500 for URL: http://myserver/sites/asite/_vti_bin/Lists.asmx?WSDL
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1241)
at java.net.URL.openStream(URL.java:1009)
at com.uboc.sharepoint.io.URLGetter.loadURLToStrings(URLGetter.java:26)
at com.uboc.sharepoint.io.URLGetter.main(URLGetter.java:105)
I tried every variation of the userid and password. This included:
1 - Using the domain name as a prefix with a backslash seperator. (<DomainName>\<UserName>)
2 - Using the system property -Dhttp.auth.ntlm.domain=<DomainName>
3 - Omitting the domain name alltogether
None of these work for me.
Does anyone know whether Sun's Linux implementation of JDK 1.6 supports NTLMv2 authentication protocol?
My authenticator code is as follows:
import java.net.Authenticator;
import java.net.PasswordAuthentication;
public class WindowsAuthenticator extends Authenticator {
private String user;
private String password;
public WindowsAuthenticator()
{
super();
}
public WindowsAuthenticator(String user, String password)
{
this.user = user;
this.password = password;
}
@Override
protected PasswordAuthentication getPasswordAuthentication()
{
PasswordAuthentication auth;
System.out.println("RequestingHost=" + this.getRequestingHost());
System.out.println("RequestingProtocol=" + this.getRequestingProtocol());
System.out.println("RequestingPort=" + this.getRequestingPort());
System.out.println("RequestingScheme=" + this.getRequestingScheme());
System.out.println("RequestingPrompt=" + this.getRequestingPrompt());
System.out.println("RequestingSite=" + this.getRequestingSite());
System.out.println("RequestingURL=" + this.getRequestingURL().toString());
if (this.getRequestorType() == Authenticator.RequestorType.PROXY)
{
System.out.println("RequestType=PROXY");
}
else if (this.getRequestorType() == Authenticator.RequestorType.SERVER)
{
System.out.println("RequestType=SERVER");
}
System.out.println("UserID=\"" + this.getUser() +"\"");
System.out.println("Password=\"" + this.getPassword()+ "\"");
auth = new PasswordAuthentication(this.user, this.password.toCharArray());
return auth;
}
/**
* @return the password
*/
public String getPassword()
{
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password)
{
this.password = password;
}
/**
* @return the user
*/
public String getUser()
{
return user;
}
/**
* @param user the user to set
*/
public void setUser(String user)
{
this.user = user;
}
}
My URLGetter Code is as follows
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Authenticator;
import java.net.URL;
import java.util.ArrayList;
public class URLGetter {
public static ArrayList<String> loadURLToStrings( URL url )
throws IOException
{
String inputLine;
ArrayList<String> lines = new ArrayList<String>();
/*
** get an input stream for the URL
*/
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
/*
** Move the data. OK maybe buffered IO might improve performance.
*/
while ( (inputLine = in.readLine()) != null )
{
lines.add(inputLine);
}
/*
** Close the stream
*/
in.close();
return lines;
}
/**
* @param args URL, outputFile, userid, password
*/
public static void main(String[] args)
{
String url = null;
String outFile = null;
String user = null;
String password = null;
PrintStream out = null;
WindowsAuthenticator auth = null;
try
{
/*
* Get the URL
*/
if (args.length > 0 )
{
url = args[0];
}
else
{
System.err.println("Error: URL not specified.");
cmdLineInfo();
System.exit(1);
}
/*
* Get the output file name
*/
if (args.length > 1 )
{
outFile = args[1];
out = setupPrintStream( outFile);
}
else
{
out = System.out;
System.err.println("Using stdout.");
}
/*
* Get the userid
*/
if (args.length > 2 )
{
user = args[2];
auth = new WindowsAuthenticator();
auth.setUser(user);
Authenticator.setDefault(auth);
System.err.println("userid specified.");
}
/*
* Get the password
*/
if (args.length > 3 )
{
password = args[3];
auth.setPassword(password);
System.err.println("password specified.");
}
/*
* Download the URL
*/
ArrayList<String> data = loadURLToStrings(new URL( url ));
for ( int i = 0; i < data.size(); i++)
{
out.println( data.get(i));
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Prints the command line parameters to the console
*
*/
public static void cmdLineInfo()
{
System.err.println("Usage: java [options] URLGetter URL outputFileName [userid] [password]");
System.err.println("Where command line parameters include:");
System.err.println("URL The full qualified URL or address of the information to download.");
System.err.println("outputFile The name of the file to save downloaded info.");
System.err.println("userid The optional username when the URL requires login.");
System.err.println("password The optional password when the URL requires login.");
}
/**
* Setup output File
*
* @param fileName
* file that will be used to create an output file
*/
public static PrintStream setupPrintStream( String fileName ) throws FileNotFoundException
{
PrintStream out = null;
File file = new File( fileName );
file.delete();
FileOutputStream stream = new FileOutputStream(fileName, true);
out = new PrintStream( stream );
return out;
}
}