使用WS-Security UsernameToken PasswordDigest身份validation方案的WCF客户端使用Axis 2 Web服务时出错

我有一个WCF客户端连接到基于Java的Axis2 Web服务(在我的控制之外)。 它即将应用WS-Security,我需要修复.NET客户端。 但是,我正在努力提供正确的身份validation。 我知道WSE 3.0可能会让它变得更容易,但我宁愿不再使用过时的技术。

类似的问题(未解决),包括这个 , 这个和这个 。

SOAP消息如下所示:

    2010-05-28T12:50:33.675+01:00  

但是,我的看起来像这样:

     2010-06-23T10:31:23.441Z 2010-06-23T10:36:23.441Z            

我的客户端看起来像这样:PS注意所需的 SecurityHeaderType参数。 那是什么?

 public MyAck SendRequest(MyRequest request) { RemoteServicePortTypeClient client = new RemoteServicePortTypeClient(); client.ClientCredentials.UserName.UserName = "JAY"; client.ClientCredentials.UserName.Password = "AND"; // what is the difference between the two different Credential types?? //client.ClientCredentials.HttpDigest.ClientCredential.UserName = "SILENT"; //client.ClientCredentials.HttpDigest.ClientCredential.Password = "BOB"; SecurityHeaderType sht = new SecurityHeaderType(); //sht.Any = ???; // How do I use this??? //sht.AnyAttr = ???; // How do I use this ??? // SecurityHeaderType is a required parameter return client.RemoteServiceOperation_Provider(sht, request); } 

目前的绑定如下:

         

我也尝试过自定义绑定并得到类似的错误:

        

和端点(地址明显改变了……):

  

返回的自定义错误如下:

 0 UNEXPECTED  2010-06-23T13:28:54Z 

我已经阅读了很多关于自定义标题,标记,绑定和我的大脑完全混淆。 任何人都可以建议一步一步的过程以正确的格式发送消息吗?

这似乎是使用自定义令牌的WCF的前进方向,但是如何根据需要应用摘要和随机数?

欢迎任何帮助。

UPDATE

我的成功有限。 我已经使用Microsoft.Web.Services3库来创建具有正确摘要的UsernameToken。 然后我创建了自己的自定义行为,在BeforeSendRequest方法中,我已完成以下操作以注入标头:

 object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) { UsernameToken ut = new UsernameToken("USERNAME", "PASSWORD", PasswordOption.SendHashed); XmlElement securityElement = ut.GetXml(new XmlDocument()); MessageHeader myHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityElement, false); request.Headers.Add(myHeader); return Convert.DBNull; } 

我添加了这样的行为:

 CustomBehavior behavior = new CustomBehavior("USERNAME", "PASSWORD"); client.Endpoint.Behaviors.Add(behavior); 

我现在可以看到标题:

             2010-06-24T16:23:58Z    

但是我收到了错误:

  soapenv:Server WSDoAllReceiver: security processing failed; nested exception is: org.apache.ws.security.WSSecurityException: General security error (WSSecurityEngine: Callback supplied no password for: USERNAME) urn:Remote_Provider   0 UNEXPECTED  2010-06-24T17:23:59Z    

密码节点上似乎缺少Type属性:

 Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest" 

但是,我不确定安全跟踪和日志记录设置是否全面删除这些节点的属性和内容。 我试图在诊断日志记录中使用logKnownPii设置,但安全信息仍然模糊不清。 关于那个的任何想法?

我可以确认我的问题的UPDATE确实有效:

 object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) { UsernameToken ut = new UsernameToken("USERNAME", "PASSWORD", PasswordOption.SendHashed); XmlElement securityElement = ut.GetXml(new XmlDocument()); MessageHeader myHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityElement, false); request.Headers.Add(myHeader); return Convert.DBNull; } 

和客户:

 CustomBehavior behavior = new CustomBehavior("USERNAME", "PASSWORD"); client.Endpoint.Behaviors.Add(behavior); 

错误消息不相关。 安全标头使用非常简单的basicHttpBinding:

      

可以在我的博客上找到此代码示例: http : //benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/

这个问题写得很好 – 非常感谢。 在参考@ Junto的“我如何使用此”注释时,事实certificate服务方法上的SecurityHeader参数可用于添加标头。 我在下面列举了一个例子。 我相信正在发生的事情是,当尝试读取WS * DTD时,SvcUtil.exe工具正在调试。 使用“添加服务引用”向导时,这并不明显。 但是从命令行运行svcutil.exe时非常明显。 因为svcutil.exe无法读取WS * DTD,所以SecurityHeader对象没有很好地开发。 但微软为您提供了.Any属性。 您可以将UsernameToken类序列化到.Any属性中,并且您的标题将添加到消息中。 再次感谢这个优秀的问题。

如何使用SecurityHeader参数添加UsernameToken安全标头:

所需工具:

Fiddler2(或类似的) – 如果不检查http标头,你真的无法解决这个问题。

必修参考:

 Microsoft.Web.Services3.dll -- you can reference this 2.0 framework assembly from your 4.0 assembly 

WCF服务电话:

 // Initialization of the service... _service = new MyService("MyEndpoint", RemoteUri); // etc. // Calling the service -- note call to GetSecurityHeader() _service.ServiceAction(GetSecurityHeader(), "myParam1"); // etc. ///  /// Construct the WSE 3.0 Security Header ///  private SecurityHeader GetSecurityHeader() { SecurityHeader h = new SecurityHeader(); UsernameToken t = new UsernameToken(RemoteLogin, RemotePassword, PasswordOption.SendPlainText); h.Any = new XmlElement[1]; h.Any[0] = t.GetXml(new XmlDocument()); return h; } 

App.config中:

                  

我最近遇到了类似的问题,并放弃了搜索非WSE解决方案。 在我拔掉头发几天之后,我结束了下载WSE 3.0 SDK,使用WseWsdl3.exe生成代理类,并为UsernameToken创建新策略。 我在15分钟内跑起来。 以下内容目前正在为我工​​作。

 RemoteService service = new RemoteService(); //generated class UsernameToken token = new UsernameToken(username, password, PasswordOption.SendPlainText); Policy policy = new Policy(); policy.Assertions.Add(new UsernameOverTransportAssertion()); service.SetClientCredential(token); service.SetPolicy(policy); var result = service.MethodCall();