23

我需要从 Java 调用用 .NET 编写的 Web 服务。Web 服务实现了 WS-Security 堆栈(WSE 2 或 WSE 3,从我掌握的信息中并不清楚)。

我从服务提供者那里收到的信息包括 WSDL、一个 policyCache.config 文件、一些示例 C# 代码和一个可以成功调用该服务的示例应用程序。

这并不像听起来那么有用,因为不清楚我应该如何使用这些信息来编写 Java 客户端。如果 Web 服务请求未根据策略签名,则它会被服务拒绝。我正在尝试使用 Apache Axis2,但找不到任何关于我应该如何使用 policyCahce.config 文件和 WSDL 来生成客户端的说明。

我在 Web 上找到了几个示例,但在所有情况下,示例的作者都控制了服务和客户端,因此能够在双方进行调整以使其正常工作。我不在那个位置。

有没有人成功做到这一点?

4

5 回答 5

10

WS-Security 规范通常不包含在 WSDL 中(从不在 WSE WSDL 中)。所以 wsdl2java 不知道这个服务甚至需要 WS-Security。WSE WSDL 中不存在安全约束这一事实让我非常失望(WCF 将在 WSDL 中包含 WS-Trust 信息)。

在客户端,您需要使用Rampart将必要的 WS-Security 标头添加到您的传出客户端消息中。由于 WSDL 没有报告哪些 WS-Security 设置是必需的,因此您最好询问服务提供者需要什么。WS-Security 要求可能是简单的明文密码,也可能是 X509 证书,也可能是加密消息……Rampart 应该能够处理大多数这些场景。

Apache Rampart 通过在您的axis2.xml 文件中使用模块来“打开”。您需要下载 Rampart 模块并将其放在 axis2 目录中的特定位置,然后修改 xml 文件。您还可以通过编程方式参与 Rampart(如果这是必需的,请编辑您的原始问题,我将编辑此回复)。

根据您配置壁垒的方式(通过其他 XML 文件或以编程方式),它将拦截任何传出消息并向其添加必要的 WS-Security 信息。我个人使用带有壁垒的axis2来调用WSE3服务,该服务使用UsernameToken以明文形式进行保护,效果很好。类似但更高级的场景也应该有效。在上面链接的网站上有更多关于如何设置和开始使用 Rampart 的详细信息。如果您对 Rampart 的细节或如何将 Rampart 与您的特定 WSE 设置一起使用有疑问,请编辑您的问题,我会尽力回答。

于 2008-09-17T14:23:23.587 回答
10

这似乎是一个受欢迎的问题,所以我将概述我们在这种情况下所做的事情。

.NET 中构建的服务似乎遵循较旧的 ws-addressing 标准 ( http://schemas.xmlsoap.org/ws/2004/03/addressing/ ) 而axis2 只理解较新的标准 ( http://schemas. xmlsoap.org/ws/2004/08/addressing/)。

另外,提供的policyCache.config文件是axis2 armart模块无法理解的形式。

所以我们必须做的步骤,简而言之:

  • 阅读 policyCache.config 并尝试理解它。然后把它改写成壁垒能理解的策略。(一些更新的文档有所帮助。)
  • 使用此策略配置壁垒。
  • 获取 .pfx 文件中提供的密钥并将它们转换为 java 密钥库。Jetty 附带的实用程序可以做到这一点。
  • 使用该密钥库配置壁垒。
  • 编写一个自定义axis2处理程序,将来自axis2的较新的ws寻址内容向后转换为服务预期的旧内容。
  • 将axis2 配置为对传出消息使用处理程序。

最后,它需要很多配置和代码,这些东西应该是供应商支持的开放标准。

虽然我不确定替代方案是什么......你能等待供应商(或者在这种情况下,一个供应商)以确保一切都可以互操作吗?

作为附言,我要补充一点,我最终并没有完成这项工作,这是我团队中的其他人,但我认为我的重要细节是正确的。我正在考虑的另一个选择(在我的队友接手之前)是直接调用 WSS4J API 来构造 SOAP 信封,就像 .NET 服务所期望的那样。我认为那也会奏效。

于 2009-04-02T20:08:38.633 回答
3

@麦克风

我最近做了一个测试,这是我使用的代码。我没有使用策略的东西,但我使用了带有纯文本身份验证的 WS-Security。CXF 有关于如何完成这些东西的非常好的文档。

我使用了 wsdl2java,然后添加了此代码以使用带有 ws-security 的 Web 服务。

我希望这能够帮到你。

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.handler.WSHandlerConstants;

public class ServiceTest implements CallbackHandler
{

     public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

            WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
            // set the password for our message.
            pc.setPassword("buddah");
        }

    public static void main(String[] args){
        PatientServiceImplService locator = new PatientServiceImplService();
        PatientService service = locator.getPatientServiceImplPort();

        org.apache.cxf.endpoint.Client client = org.apache.cxf.frontend.ClientProxy.getClient(service);
        org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();

        Map<String, Object> outProps = new HashMap<String, Object>();
        outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN + " " +  WSHandlerConstants.TIMESTAMP);
        outProps.put(WSHandlerConstants.USER, "joe");
        outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

        // Callback used to retrieve password for given user.
        outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ServiceTest.class.getName());

        WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
        cxfEndpoint.getOutInterceptors().add(wssOut);


        try
        {
            List list = service.getInpatientCensus();
            for(Patient p : list){
                System.out.println(p.getFirstName() + " " + p.getLastName());
            }

        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
于 2008-08-19T21:18:27.643 回答
2
于 2008-08-19T16:19:51.177 回答
0

CXF - 我会研究 CXF。我已经使用它使用 ws-secuirty 在 java 中创建 Web 服务和客户端。我还连接了一个 .net 网络服务。

他们也有很好的文档。我比轴更幸运。

于 2008-08-19T16:06:09.003 回答