将 NTLM 与 Wildfly 一起使用的 HTTP 响应“401:未经授权”
HTTP response '401: Unauthorized' using NTLM with Wildfly
当 SOAP 请求太长时,我们在 WildFly 11(Apache CXF 底层)中使用 JAX-WS 得到 '401: Unauthorized'
作为响应。
我们使用 NTLM 协议从 WildFly 调用 SOAP Web 服务到 SharePoint。
如果请求大小很短,它工作正常,但如果请求是 "large"(例如 1MB 的 SOAP 消息),它会失败并显示错误 HTTP 401。我们正在使用此 Web 服务发送图像,但编码为 base64 二进制文件。
我们尝试使用 SOAP UI 调用该服务并且成功了,所以它似乎是应用程序服务器中的一个问题。可能会发生什么,我们可以使用哪些解决方法?
更新: Jira issue CXF-5890 好像有点类似这个
我们的客户端代码很简单,我们发送一个BASE64字节数组(s:base64Binary):
@Stateless
public class Client {
@WebServiceRef(wsdlLocation = "/wsdl/service.wsdl")
private ServiceRepository service;
public void send() {
Repository repository = service.getRepositorySoap();
Map<String, Object> requestContext = ((BindingProvider) repository).getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://customerendpoint/service.asmx");
// sets standard Java authentication for NTLM
authtWsSharepoint();
// This method loads an image in BASE64. We found the problem around 45,000 characters, but it is not exact
String image = getImage();
repository.submitFile(image.getBytes());
}
}
我们正在使用标准 Java 验证器:
private void authtWsSharepoint() throws Exception {
Authenticator sAuthService = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("domain\user", "password".toCharArray());
}
};
Authenticator.setDefault(sAuthService);
}
例外情况:
Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '401: Unauthorized' when communicating with http://customerendpoint/service.asmx
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1581)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1533)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1336)
at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:56)
at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:215)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:652)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:516)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:425)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:326)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:279)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:138)
... 110 more
奇迹发生在这里httpClientPolicy.setAllowChunking(false)
。将此设置为 false 解决了问题。
代码示例
Client client = ClientProxy.getClient(servicePort);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
//This is the magic line. Setting this to false solved the problem
httpClientPolicy.setAllowChunking(false);
http.setClient(httpClientPolicy);
依赖项
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-simple</artifactId>
<version>3.0.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.0.5</version>
<scope>provided</scope>
</dependency>
jboss-部署-structure.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.apache.cxf.impl">
<imports>
<include path="META-INF"/>
<include path="META-INF/cxf"/>
</imports>
</module>
</dependencies>
</deployment>
</jboss-deployment-structure>
当 SOAP 请求太长时,我们在 WildFly 11(Apache CXF 底层)中使用 JAX-WS 得到 '401: Unauthorized'
作为响应。
我们使用 NTLM 协议从 WildFly 调用 SOAP Web 服务到 SharePoint。
如果请求大小很短,它工作正常,但如果请求是 "large"(例如 1MB 的 SOAP 消息),它会失败并显示错误 HTTP 401。我们正在使用此 Web 服务发送图像,但编码为 base64 二进制文件。
我们尝试使用 SOAP UI 调用该服务并且成功了,所以它似乎是应用程序服务器中的一个问题。可能会发生什么,我们可以使用哪些解决方法?
更新: Jira issue CXF-5890 好像有点类似这个
我们的客户端代码很简单,我们发送一个BASE64字节数组(s:base64Binary):
@Stateless
public class Client {
@WebServiceRef(wsdlLocation = "/wsdl/service.wsdl")
private ServiceRepository service;
public void send() {
Repository repository = service.getRepositorySoap();
Map<String, Object> requestContext = ((BindingProvider) repository).getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://customerendpoint/service.asmx");
// sets standard Java authentication for NTLM
authtWsSharepoint();
// This method loads an image in BASE64. We found the problem around 45,000 characters, but it is not exact
String image = getImage();
repository.submitFile(image.getBytes());
}
}
我们正在使用标准 Java 验证器:
private void authtWsSharepoint() throws Exception {
Authenticator sAuthService = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("domain\user", "password".toCharArray());
}
};
Authenticator.setDefault(sAuthService);
}
例外情况:
Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '401: Unauthorized' when communicating with http://customerendpoint/service.asmx
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1581)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1533)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1336)
at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:56)
at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:215)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:652)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:516)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:425)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:326)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:279)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:138)
... 110 more
奇迹发生在这里httpClientPolicy.setAllowChunking(false)
。将此设置为 false 解决了问题。
代码示例
Client client = ClientProxy.getClient(servicePort);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
//This is the magic line. Setting this to false solved the problem
httpClientPolicy.setAllowChunking(false);
http.setClient(httpClientPolicy);
依赖项
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-simple</artifactId>
<version>3.0.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.0.5</version>
<scope>provided</scope>
</dependency>
jboss-部署-structure.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.apache.cxf.impl">
<imports>
<include path="META-INF"/>
<include path="META-INF/cxf"/>
</imports>
</module>
</dependencies>
</deployment>
</jboss-deployment-structure>