我正在尝试使用NT Apache CXF中提到的使用NTLM身份验证的SOAP Web服务进行身份验证,其堆栈如下所示 -
每当我尝试连接时,它都会拒绝401未经授权的访问,因为它使用的是未经授权的基础NT凭据,而不是我在代码中配置的有效凭证。 (我不得不修改jCIFS,因为它不支持SSL + NTLM来返回NtlmHttpURLConnection的HTTPs版本)。使用HTTP异步机制时的结果相似。
String domainController = "xxx.xxx.xxx";
UniAddress dc = UniAddress.getByName(domainController, true);
jcifs.Config.setProperty("http.auth.ntlm.domain", "xxx.xxx.xxx");
jcifs.Config.setProperty("jcifs.smb.client.domain", "domain");
jcifs.Config.setProperty("jcifs.netbios.wins", dc.getHostAddress());
jcifs.Config.setProperty("jcifs.smb.client.soTimeout", "300000"); // 5 minutes
jcifs.Config.setProperty("jcifs.netbios.cachePolicy", "1200"); // 20 minutes
jcifs.Config.setProperty("jcifs.smb.client.username", USER);
jcifs.Config.setProperty("jcifs.smb.client.password", PWD);
//Register the jcifs URL handler to enable NTLM
jcifs.Config.registerSmbURLHandler();
HelloWorld src = new HelloWorld();
ClientProxyFactoryBean factory = new ClientProxyFactoryBean(new JaxWsClientFactoryBean());
factory.setServiceClass( IHelloWorld.class );
factory.setAddress(SERVICE_URL);
factory.setUsername(USER);
factory.setPassword(PWD);
IHelloWorld service = (IHelloWorld ) factory.create();
Client client = ClientProxy.getClient(service);
HTTPConduit http = (HTTPConduit) client.getConduit();
System.out.println(http.getClass().getName());
//org.apache.cxf.transport.http.URLConnectionHTTPConduit
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
http.setClient(httpClientPolicy);
http.getAuthorization().setAuthorizationType("NTLM");
http.getAuthorization().setUserName(USER);
http.getAuthorization().setPassword(PWD);
http.getClient().setAllowChunking( false );
http.getClient().setAutoRedirect( true );
TLSClientParameters tcp = new TLSClientParameters();
tcp.setTrustManagers( new TrustManager[]{ new TrustAllX509TrustManager() } );
http.setTlsClientParameters( tcp );
System.out.println("Invoking service...");
String msg= "echo";
try {
String res = service.readMessage(msg);
System.out.println("readMessage.result=" + res);
} catch (Exception e) {
e.printStackTrace();
}
Upong运行此代码我得到以下异常跟踪
:domain \是未经授权的用户 sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法) at sun.reflect.NativeConstructorAccessorImpl.newInstance(未知 来源)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(未知 来自java.lang.reflect.Constructor.newInstance(未知来源) 在 org.apache.cxf.interceptor.ClientFaultConverter.processFaultDetail(ClientFaultConverter.java:175) 在 org.apache.cxf.interceptor.ClientFaultConverter.handleMessage(ClientFaultConverter.java:78) 在 org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) 在 org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:113) 在 org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69) 在 org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34) 在 org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:845) 在 org.apache.cxf.transport.http.HTTPConduit $ WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1624) 在 org.apache.cxf.transport.http.HTTPConduit $ WrappedOutputStream.handleResponse(HTTPConduit.java:1513) 在 org.apache.cxf.transport.http.HTTPConduit $ WrappedOutputStream.close(HTTPConduit.java:1318) 在 org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56) 在 org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:632) 在 org.apache.cxf.interceptor.MessageSenderInterceptor $ MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62) 在 org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) 在org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:570) 在org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:479)at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382)at at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335)at at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96) 在org.apache.cxf.frontend.ClientProxy.invoke(ClientProxy.java:81) 在com.sun.proxy。$ Proxy44.readMessage(未知来源)
答案 0 :(得分:1)
CXF 2.7.x不支持JDK 5.来自CXF FAQ:
CXF可以运行JDK 1.5吗?
适用于CXF 2.6.x及更早版本。请记住Java 2 SE 5.0 JDK 1.5已达到使用寿命终止(EOL)。不再使用CXF 2.7.x. 支持Java 5.要升级到2.7.x,您必须使用Java 6(或更新)。
答案 1 :(得分:1)
经过几个小时的努力试图在JDK 5堆栈和其他SOAP框架(如Axis2和CXF)之间徘徊,我终于想到了一个原始的SOAP客户端,它可以完成我所需要的工作。以下是使用自定义NT登录而不是基础登录的帮助完成它的代码。
public final class JCIFSEngine implements NTLMEngine {
private static final int TYPE_1_FLAGS = NtlmFlags.NTLMSSP_NEGOTIATE_56
| NtlmFlags.NTLMSSP_NEGOTIATE_128
| NtlmFlags.NTLMSSP_NEGOTIATE_NTLM2
| NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN
| NtlmFlags.NTLMSSP_REQUEST_TARGET;
public String generateType1Msg(final String domain, final String workstation)
throws NTLMEngineException {
final Type1Message type1Message = new Type1Message(TYPE_1_FLAGS,
domain, workstation);
return Base64.encode(type1Message.toByteArray());
}
public String generateType3Msg(final String username,
final String password, final String domain,
final String workstation, final String challenge)
throws NTLMEngineException {
Type2Message type2Message;
try {
type2Message = new Type2Message(Base64.decode(challenge));
} catch (final IOException exception) {
throw new NTLMEngineException("Invalid NTLM type 2 message",
exception);
}
final int type2Flags = type2Message.getFlags();
final int type3Flags = type2Flags
& (0xffffffff ^ (NtlmFlags.NTLMSSP_TARGET_TYPE_DOMAIN | NtlmFlags.NTLMSSP_TARGET_TYPE_SERVER));
final Type3Message type3Message = new Type3Message(type2Message,
password, domain, username, workstation, type3Flags);
return Base64.encode(type3Message.toByteArray());
}
}
public class JCIFSNTLMSchemeFactory implements AuthSchemeProvider {
public AuthScheme create(final HttpContext context) {
return new NTLMScheme(new JCIFSEngine());
}
}
使用HttpClient对象注册自定义NTLM引擎和身份验证方案注册表 -
protected Registry<AuthSchemeProvider> getAuthRegistry() {
Registry<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder
.<AuthSchemeProvider> create()
.register(AuthSchemes.NTLM, new JCIFSNTLMSchemeFactory())
.build();
return authSchemeRegistry;
}
protected CredentialsProvider getCredentialsProvider(String user,
String pass, String domain) {
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST,
AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthSchemes.NTLM),
new NTCredentials(user, pass, null, domain));
return credsProvider;
}
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setDefaultAuthSchemeRegistry(getAuthRegistry());
httpClientBuilder
.setDefaultCredentialsProvider(getCredentialsProvider(
config.getUserName(), config.getPassword(),
config.getDomain()));
if (config.isProxy()) {
HttpHost proxy = new HttpHost(config.getProxyHost(),
config.getPort());
httpClientBuilder.setProxy(proxy);
}
httpClientBuilder.build();
希望这可以帮助有类似问题的人。干杯