我正在尝试使用Java和Apache的cxf库进行Web服务调用,当然,如果可能的话,这应该使用摘要式身份验证,如果服务器不支持摘要,则基本作为回退。
我有以下代码,从WSDL创建一个服务端口,创建一个HTTPConduit,它能够处理身份验证协商,并设置所需的授权类型“Digest”。
MyService myService = new MyService("wsdl-url");
MyServicePort myServicePort = myService.getMyServicePort();
Client client = ClientProxy.getClient(myServicePort);
HTTPConduit http = (HTTPConduit) client.getConduit();
AuthorizationPolicy authPolicy = new AuthorizationPolicy();
authPolicy.setAuthorizationType("Digest");
authPolicy.setUserName("user");
authPolicy.setPassword("myPassword");
http.setAuthorization(authPolicy);
myServicePort.doSomething();
现在,如果服务器仅响应接受摘要式身份验证,则可以正常工作,因此使用标头:
WWW-Authenticate: Digest realm="...", nonce="...", algorithm=MD5, qop="auth"\r\n
但还有另一台服务器(服务器实际上是摄像机),它通过提供身份验证方法,基本和摘要来响应:
WWW-Authenticate: Digest realm="...", nonce="...", stale=FALSE, qop="auth"\r\n
WWW-Authenticate: Basic realm="..."\r\n
它会失败,因为不会发送重传。我猜cxf只选择了两种方法中的一种,这种方法很基本,但没有找到基本方法的授权策略,因此它失败了。
以下是一些堆栈跟踪:
Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '401: Unauthorized' when communicating with http://192.168.x.x/vapix/services
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.doProcessResponseCode(HTTPConduit.java:1600) ~[cxf-rt-transports-http-3.1.8.jar:3.1.8]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1607) ~[cxf-rt-transports-http-3.1.8.jar:3.1.8]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1551) ~[cxf-rt-transports-http-3.1.8.jar:3.1.8]
有人知道这是否是cxf的错误?或者有解决方法吗?我唯一的想法是编写我自己的HttpAuthSupplier,但这可能有点微妙。
谢谢, 西尔