SOAP服务在SOAP UI正常运行,Java代码调用失败求助
我之前也踩过一模一样的坑!SOAP UI里填完用户名密码就能正常调用,一用Java代码就卡认证,真的让人头大。咱们一步步来排查解决:
先确认认证类型是否匹配
首先得搞清楚你在SOAP UI里用的是哪种认证:是Basic Auth(直接在认证标签选Basic填账号密码),还是WS-Security(添加了Username Token那种)?这俩的Java代码配置完全不一样,错了肯定调用失败。
情况1:用的是Basic认证
如果你SOAP UI里用的是Basic Auth,那直接给Axis生成的Stub对象设置用户名密码就行——你代码里用的是Axis框架生成的客户端(ServicesLocator、SoapProxy这些都是Axis的类),可以这么改:
ServicesLocator sl = new ServicesLocator(); // 获取服务端口实例 ServicesSoap serviceSoap = sl.getServicesSoap(); // 转换成Axis的Stub对象,它自带Basic认证设置方法 Stub stub = (Stub) serviceSoap; // 填入你的用户名和密码 stub.setUsername("你的用户名"); stub.setPassword("你的密码"); // 接下来正常调用服务方法就行 stub.yourTargetServiceMethod();
你之前的代码里绕了Proxy,其实直接通过Locator拿到端口转成Stub更直接,Axis的Stub已经封装了Basic认证的逻辑,不用自己拼请求头。
情况2:用的是WS-Security认证
如果是给SOAP消息加了WS-Security的Username Token(SOAP UI里可能是在WS-Security标签里配置的),那得手动给Java请求添加安全头,SOAP UI是自动帮你生成的,但Java代码得自己实现。可以用Apache WSS4J来搞定:
- 先确保项目引入了WSS4J的依赖(Maven的话直接加对应的dependency就行)
- 给Stub配置WS-Security Handler:
ServicesLocator sl = new ServicesLocator(); ServicesSoap serviceSoap = sl.getServicesSoap(); Stub stub = (Stub) serviceSoap; // 创建WS-Security处理器 WSS4JHandler handler = new WSS4JHandler(); Map<String, Object> config = new HashMap<>(); // 指定要添加Username Token config.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); config.put(WSHandlerConstants.USER, "你的用户名"); // 密码类型,看服务端要求是明文还是摘要,这里先填明文示例 config.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); // 指定密码回调类,用来提供密码 config.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallbackImpl.class.getName()); // 把处理器加到Stub的处理器列表里 List<Handler> handlers = new ArrayList<>(); handlers.add(handler); stub._setProperty(Stub.HANDLER_SET, handlers); // 自己实现密码回调类 class PasswordCallbackImpl implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback passwordCallback = (WSPasswordCallback) callbacks[0]; passwordCallback.setPassword("你的密码"); } }
额外排查点:端点地址是否正确
你代码里提到了proxy.getEndpoint(...),有时候自动生成的客户端端点地址可能和SOAP UI里用的不一样(比如测试/生产环境差异、路径拼写错误),可以打印出来对比一下:
System.out.println(stub._getEndpoint());
如果和SOAP UI里的地址不一致,用stub._setEndpoint("正确的服务地址")来修正。
终极排查:抓包对比请求
要是上面的方法都不行,建议用抓包工具(比如Fiddler)把SOAP UI的成功请求和Java代码的失败请求抓下来对比,看看认证头、SOAP消息结构有啥差异——毕竟SOAP UI能成,说明请求格式肯定是对的,Java代码的请求肯定哪里有不一样的地方,一对比就能找到问题。
内容的提问来源于stack exchange,提问作者Krishna

