从Java调用.NET Web服务(WSE 2/3,WS-Security)

时间:2008-08-19 15:54:59

标签: java .net axis2 ws-security wse

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

我从服务提供商处收到的信息包括WSDL,policyCache.config文件,一些示例C#代码以及可以成功调用该服务的示例应用程序。

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

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

有没有人成功完成这项工作?

5 个答案:

答案 0 :(得分: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应该能够处理大多数这些场景。

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

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

答案 1 :(得分:10)

这似乎是一个受欢迎的问题,因此我将概述我们在我们的情况下所做的工作。

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

此外,提供的policyCache.config文件采用的是axis2 rampart模块无法理解的形式。

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

  • 阅读policyCache.config并尝试理解它。然后将其重写为一个可以理解的策略。 (有些updated docs帮助了。)
  • 使用此策略配置rampart。
  • 获取.pfx文件中提供的密钥并将其转换为Java密钥库。 Jetty有一个实用程序可以做到这一点。
  • 使用该密钥库配置rampart。
  • 编写一个自定义的axis2处理程序,将来自axis2的较新的ws-addressing内容向后转换为服务所需的旧内容。
  • 配置axis2以在外发邮件上使用处理程序。

最后,很多配置和代码都应该是供应商支持的开放标准。

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

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

答案 2 :(得分:3)

@Mike

我最近做了一个测试,这是我使用的代码。 我没有使用策略,但我使用了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();
        }
    }
}

答案 3 :(得分:2)

答案 4 :(得分:0)

CXF - 我会看看CXF。我用它来使用ws-secuirty在java中创建一个Web服务和客户端。我还将.net网络服务连接到它。

他们也有很好的文档。我比它有更多的运气。