gpt4 book ai didi

java - 使用 apache cxf 的 soap web 服务客户端,用于 ntlm 身份验证

转载 作者:搜寻专家 更新时间:2023-11-01 03:51:51 27 4
gpt4 key购买 nike

我想开发一个使用 CXF 连接到 SharePoint 的 SOAP 客户端。 身份验证方案是 NTLM

在某台计算机(正在运行 SOAP 客户端)的登录用户有权访问 SharePoint 的情况下,我被阻止了。 CXF soap 客户端始终使用登录用户。 我想指定一些其他用户凭据(不是已登录的)。

由于 CXF 在 JDK 中使用 HttpURLConnection;我读到的关于 HttpURLConnection 的内容是,当登录用户通过 NTLM 身份验证时,它会绕过指定的凭据。

代码已在 CXF 版本 2.7.11 上进行了尝试。


我尝试过的解决方案:

1) 设置Conduit权限

String username = "user";     
String password = "password";

JaxWsProxyfactoryBean factory1 = new JaxWsProxyfactoryBean();
factory1.setServiceClass(WebsSoap.class);
factory1.setAddress(url);
factory1.setUsername(username);
factory1.setPassword(password);

WebsSoap service = (WebsSoap) factory1.create();
Client client = ClientProxy.getClient(service);

HTTPconduit conduit = (HTTPconduit) client.getconduit();
conduit.getAuthorization().setAuthorizationType("NTLM");
conduit.getAuthorization().setUserName(username);
conduit.getAuthorization().setPassword(password);

HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
conduit.setClient(httpClientPolicy);

service.getWeb(".");

问题:

这不适用于上面指定的场景,因为它始终使用登录凭据。当我指定无效凭据时,它不会失败。


2) AsyncHTTPConduit

另一种解决方案是使用 AsyncHTTPConduit,它使用 HttpAsyncClient 而不是 HttpURLConnection。这是因为 HTTP 组件不会绕过指定的凭据,并且可以忽略已登录的用户(我已经使用 HttpClient 通过测试客户端成功验证了这一点)。

下面是代码片段::

Bus bus = BusFactory.getDefaultBus();    
bus.setProperty( "use.async.http.conduit", "true" );

Client client = ClientProxy.getClient( service );
HTTPConduit http = (HTTPConduit)client.getConduit();
if ( http instanceof AsyncHTTPConduit ) {
AsyncHTTPConduit conduit = (AsyncHTTPConduit)http;
DefaultHttpAsyncClient defaultHttpAsyncClient;
try {
defaultHttpAsyncClient = conduit.getHttpAsyncClient();
}
catch ( IOException exception ) {
throw new RuntimeException( exception );
}
defaultHttpAsyncClient.getCredentialsProvider().setCredentials( AuthScope.ANY,
new NTCredentials( "username", "password", "", "domain" ) );
conduit.getClient().setAllowChunking( false );
conduit.getClient().setAutoRedirect( true );
}

问题:

以上代码抛出错误:

Authorization loop detected on conduit.

上面的代码快照显示了 DefaultHttpAsyncClient 的用法,现在已弃用,将使用 CloseableHttpAsyncClient 代替。但是 CloseableHttpAsyncClient 没有提供一种方法来为已经存在的 CloseableHttpAsyncClient 对象指定凭据。不确定如何在这种情况下使用 CloseableHttpAsyncClient


3) 其他解决方案

我尝试的另一个解决方案是使用 sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback 来绕过登录用户身份验证,如前所述 here .将此方法与上述解决方案 #1 一起使用。对于有效/无效凭据,这按预期工作,并且代码绕过登录凭据:)。但是,当我指定无效凭据时,我没有收到 HTTP 401 错误,而是收到了

Could not send message, server reached max retries 20

我试图避免这种解决方案,因为它使用了 java 的内部包,并且无法直接确定 HTTP 401 错误。

我该怎么做才能获得完整的解决方案?

最佳答案

试试这个拦截器。这将避免自动身份验证。

public class DisableAutomaticNTLMAuthOutInterceptor extends AbstractPhaseInterceptor<Message>
{
private boolean isFieldsAvailable;

private Field tryTransparentNTLMProxyField;

private Field tryTransparentNTLMServerField;

public DisableAutomaticNTLMAuthOutInterceptor() {
super(Phase.PRE_STREAM);

AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Void run() {
try {
DisableAutomaticNTLMAuthOutInterceptor.this.tryTransparentNTLMServerField = HttpURLConnection.class.getDeclaredField("tryTransparentNTLMServer");
DisableAutomaticNTLMAuthOutInterceptor.this.tryTransparentNTLMServerField.setAccessible(true);

DisableAutomaticNTLMAuthOutInterceptor.this.tryTransparentNTLMProxyField = HttpURLConnection.class.getDeclaredField("tryTransparentNTLMProxy");
DisableAutomaticNTLMAuthOutInterceptor.this.tryTransparentNTLMProxyField.setAccessible(true);
DisableAutomaticNTLMAuthOutInterceptor.this.isFieldsAvailable = true;

} catch (Exception e) {
e.printStackTrace();
}
return null;
}
});
}

@Override
public void handleMessage(final Message message) throws Fault {
if (this.isFieldsAvailable)
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Void run() {
try {
Object httpConnection = message.get("http.connection");
if (httpConnection != null) {
DisableAutomaticNTLMAuthOutInterceptor.this.processHttpConnection(message.get("http.connection"));
}
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
});

}

private void processHttpConnection(Object httpConnection) throws IllegalArgumentException, IllegalAccessException {

if (HttpURLConnection.class.isAssignableFrom(httpConnection.getClass())) {
tryTransparentNTLMServerField.set(httpConnection, Boolean.FALSE);
tryTransparentNTLMProxyField.set(httpConnection, Boolean.FALSE);
} else {
Field tempField = null;
for (Field field : httpConnection.getClass().getDeclaredFields()) {
if (HttpURLConnection.class.isAssignableFrom(field.getType())) {
field.setAccessible(true);
tempField = field;
break;
}
}
if (tempField != null) {
processHttpConnection(tempField.get(httpConnection));
}
}
}
}

关于java - 使用 apache cxf 的 soap web 服务客户端,用于 ntlm 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24497494/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com