Web services 在soap消息中使用wsse安全标头(Visual Studio 2015、.Net Framework 4.5)

Web services 在soap消息中使用wsse安全标头(Visual Studio 2015、.Net Framework 4.5),web-services,wcf,soap,visual-studio-2015,.net-4.5,Web Services,Wcf,Soap,Visual Studio 2015,.net 4.5,我想使用DHL提供的Soap服务。您可以在此处找到wsdl: 因此,我在Visual Studio 2015中针对.net framework 4.5创建了一个新类库 然后,我通过提供wsdl地址向创建的项目添加了一个Web引用。我生成了一个包含所有类型和端口的代理文件,但我的第一个问题是,生成的服务扩展自System.Web.Services.Protocols.SoapHttpClientProtocol。正如我在最近的文章中所读到的,不可能将wsse头发送到该代理。一些帖子建议添加wse,

我想使用DHL提供的Soap服务。您可以在此处找到wsdl:

因此,我在Visual Studio 2015中针对.net framework 4.5创建了一个新类库

然后,我通过提供wsdl地址向创建的项目添加了一个Web引用。我生成了一个包含所有类型和端口的代理文件,但我的第一个问题是,生成的服务扩展自
System.Web.Services.Protocols.SoapHttpClientProtocol
。正如我在最近的文章中所读到的,不可能将wsse头发送到该代理。一些帖子建议添加wse,但较新的Visual Studio版本似乎不支持wse

我试图通过svcutil生成我的代理。之后,我将生成的.cs文件添加到项目中,并将生成的配置文件的内容复制到app.config。(当然,我删除了web引用) 现在服务类扩展了
System.ServiceModel.ClientBase
。(我认为VS中的生成器在内部使用svctool。如果microsoft希望人们使用wcf,为什么生成器会生成非wcf代理文件

我还创建了一个nunit testproject,它应该测试我的服务,但是如果我将该版本与svcutil生成的版本一起使用,我会收到一个错误。我尝试将其翻译为英语,因为错误显示为德语:

找不到指向服务协定的默认终结点元素。我发现这是因为代理位于其自己的类库中,因此实际上没有app.config。但我的测试项目也是一个类库

现在使用需要ws-security用户名/密码验证的web服务的实际方式是什么?


您可以在兼容模式下添加Web引用(我猜您正在这样做)。如果不在兼容模式下添加引用,请执行以下操作:

右键单击references Add Service Reference->Advanced->Add Web Reference(在兼容性部分下面),键入WS的URL并添加引用

WSE2.0扩展以Nuget包的形式提供,网址为:

在运行以下nugget命令的package manager控制台上安装nuget软件包: 安装软件包Microsoft.Web.Services2

安装nuget软件包后,需要确保项目引用了以下DLL:

  • 系统.Web
  • System.Web.Services
  • Microsoft.Web.Services2(这将在安装nuget软件包后添加)
  • 为了使用WSE2.0扩展,您需要实际修改在添加WebReference以从“Microsoft.Web.Services2.WebServicesClientProtocol”而不是“System.Web.Services.Protocols.SoapHttpClientProtocol”继承时创建的代理类。请注意,如果更新WebReference,代理类将继承againfrom SoapHttpClientProtocol

    将以下using子句添加到使用代理类的代码中:

    using Microsoft.Web.Services2;
    using Microsoft.Web.Services2.Security;
    using Microsoft.Web.Services2.Security.Tokens;
    
    进行此更改后,您的代码应该如下所示:

    var token = new UsernameToken("theUser", "thePassword", PasswordOption.SendHashed);
    
    var serviceProxy = new ExpressRateBook.gblExpressRateBook();
    SoapContext requestContext = serviceProxy.RequestSoapContext;
    requestContext.Security.Timestamp.TtlInSeconds = 60;
    requestContext.Security.Tokens.Add(token);
    //The rest of the logic goes here...
    
    public consulta_informacao_respttClient CriaConsultaClinicaClient()
        {
            var client = new consulta_informacao_respttClient(defaultBinding, new EndpointAddress("https://resqa.homologacao.unimed.coop.br/chs-integration-external-services-ptu-clinical/proxy-services/execute-query/execute-query-proxy-service"));
            client.ClientCredentials.UserName.UserName = UserName;
            client.ClientCredentials.UserName.Password = Password;
    
            var scope = new OperationContextScope(client.InnerChannel);
    
            OperationContext.Current.OutgoingMessageHeaders.Add(defaultSecurityHeader);
            return client;
        }
    
    我添加了下面的屏幕截图供您参考:

    注意:我无法测试代码,因为我不熟悉您需要使用的实际方法,显示的代码只是我在代理类中看到的示例,请根据您的需要进行更新。如果您按照前面描述的步骤进行操作,应该可以正常工作。有关更详细的说明,请查看以下链接:


    您可以配置您的服务引用以添加安全标头,如AW Rowse所述:

    并按如下方式创建客户端/代理:

    var token = new UsernameToken("theUser", "thePassword", PasswordOption.SendHashed);
    
    var serviceProxy = new ExpressRateBook.gblExpressRateBook();
    SoapContext requestContext = serviceProxy.RequestSoapContext;
    requestContext.Security.Timestamp.TtlInSeconds = 60;
    requestContext.Security.Tokens.Add(token);
    //The rest of the logic goes here...
    
    public consulta_informacao_respttClient CriaConsultaClinicaClient()
        {
            var client = new consulta_informacao_respttClient(defaultBinding, new EndpointAddress("https://resqa.homologacao.unimed.coop.br/chs-integration-external-services-ptu-clinical/proxy-services/execute-query/execute-query-proxy-service"));
            client.ClientCredentials.UserName.UserName = UserName;
            client.ClientCredentials.UserName.Password = Password;
    
            var scope = new OperationContextScope(client.InnerChannel);
    
            OperationContext.Current.OutgoingMessageHeaders.Add(defaultSecurityHeader);
            return client;
        }
    
    需要在类中创建的属性包括:

    private BasicHttpBinding defaultBinding;
    private UsernameToken defaultToken;
    private MessageHeader defaultSecurityHeader;
    

    您不需要在app/web.config中配置任何内容。

    您不知道自己是一个多么了不起的人,这非常有效,感谢您提供的解决方案