问题
So I'm trying to track down a strange bug with NTLMv2 and Java. It seems like NTLM is ignoring any information I pass in during the Java based authentication, and finds the information somewhere else. Because of this, NTLM will authenticate on my machine, even if I provide the incorrect information, and won't work on any other machine even when the correct information is provided. The endpoint is the MOSS 2007 webservice API if that's relevant.
Here's the process I'm using to authenticate:
1) Pass in the target site and login info.
try {
JLists list = new JLists(siteUrl, DEFAULT_SP_USERNAME,
DEFAULT_SP_PASSWORD);
list.addList(name, description, 101);
} catch (Exception e) {
e.printStackTrace();
}
2) Set the default authenticator to my own NTLMAuthenticator,
create the service stub and pass in the login info.
public JLists(String siteURI, String username, String password)
throws Exception {
String endpointURI = siteURI + "/_vti_bin/Lists.asmx";
Authenticator.setDefault(new NtlmAuthenticator(username, password));
port = sharePointListsAuth(username, password);
BindingProvider bp = (BindingProvider) port;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
endpointURI);
}
private ListsSoap sharePointListsAuth(String userName, String password) throws Exception {
ListsSoap port = null;
if (userName != null && password != null) {
try {
service = new Lists();
port = service.getListsSoap();
((BindingProvider) port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, userName);
((BindingProvider) port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
} catch (Exception e) {
throw new Exception("Error: " + e.toString());
}
} else {
throw new Exception("Couldn't authenticate: Invalid connection details given.");
}
return port;
}
Here's a copy of the NTLMAuthenticator class as well:
import java.net.Authenticator;
import java.net.PasswordAuthentication;
class NtlmAuthenticator extends Authenticator {
private final String username;
private final char[] password;
public NtlmAuthenticator(final String username, final String password) {
super();
this.username = username;
this.password = password.toCharArray();
}
public PasswordAuthentication getPasswordAuthentication() {
return (new PasswordAuthentication (username, password));
}
}
3) Make my service call. I'm not really having any problems in this part, but if someone needs the code I'll post it as well.
I feel like Java is somehow referencing my Active Directory information, and using that instead the information provided, but I have no idea at what point that would happen.
回答1:
It seems like the problem is based around Java's "Single Sign-On" functionality. Because I am attempting NTLM authentication on Windows machine, Java has a hard-coded value that defaults to the login information of the current account, then uses the Java Authenticator only if that fails.
Seems there is no way to bypass this without decompiling the Java source and modifying that variable yourself, but thankfully that wont be needed in the end case for my application.
回答2:
you can provide your own
public class Handler extends jdk6.sun.net.www.protocol.http.Handler
which with some reflection you can get the fields of the HttpURLConnection class, and modify it.
field.setAccessible( true );
field.setBoolean( connection, false );
the fields are "tryTransparentNTLMServer" and "tryTransparentNTLMProxy";
来源:https://stackoverflow.com/questions/11162996/verifying-ntlmv2-authentication-in-java