2014-04-11 63 views
1

我構建了一個WCF客戶端來訪問供應商Web服務。該服務使用IssuedTokenOverTransport,SymmetricKey,並且期望SAML。我的請求正在工作,但服務的響應包括WS-Security頭中的SignatureConfirmation元素。我的C#客戶端扼流器在這個「簽名確認不希望在安全頭」,我沒有看到任何方式來忽略或處理這個元素。似乎在WCF中處理SignatureConfirmation的唯一方法是放棄IssuedTokenOverTransport綁定並使用其他內容,但這似乎不是一種選擇,因爲該服務需要此綁定類型。這是WCF中的錯誤嗎?IssuedTokenOverTransport響應中的意外SignatureConfirmation

+0

運行到同樣的事情在這裏......幾乎一模一樣。 –

回答

1

我通過使用自定義消息編碼器解決了這個問題。請參閱本文從卡洛斯Figueroa的背景:

http://blogs.msdn.com/b/carlosfigueira/archive/2011/11/09/wcf-extensibility-message-encoders.aspx

基本上,編碼器可以查找SignatureConfirmation元件輸入消息中並從頭部卸下。代碼的關鍵部分是這一點,從ReadMessage覆蓋稱爲私有方法:

private MemoryStream ProcessMemoryStream(Stream inputStream, bool dispose) 
    { 
     StreamWriter xmlStream = null; 
     var outputStream = new MemoryStream(); 
     bool continueFilter = false; 
     try 
     { 
      xmlStream = new StreamWriter(outputStream); 
      using (var reader = XmlReader.Create(inputStream)) 
      { 
       using (
        var writer = XmlWriter.Create(xmlStream, 
         new XmlWriterSettings() {ConformanceLevel = ConformanceLevel.Auto})) 
       { 
        while (reader.Read()) 
        { 
         if (reader.LocalName.Equals("SignatureConfirmation") && 
          reader.NamespaceURI.Equals(
           "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd")) 
         { 
          if (!reader.IsEmptyElement) continueFilter = reader.IsStartElement(); 
         } 
         else if (reader.LocalName.Equals("Signature") && 
           reader.NamespaceURI.Equals("http://www.w3.org/2000/09/xmldsig#")) 
         { 
          if (!reader.IsEmptyElement) continueFilter = reader.IsStartElement(); 
         } 
         else if (continueFilter) 
         { 
          // continue to next node 
         } 
         else 
          XmlHelper.WriteShallowNode(reader, writer); 
        } 
        writer.Flush(); 
       } 
       reader.Close(); 
      } 
      outputStream.Position = 0; 
      return outputStream; 
     } 
     catch (Exception ex) 
     { 
      // handle error 
      throw; 
     } 
     finally 
     { 
      if (xmlStream != null && dispose) xmlStream.Dispose(); 
     } 
    } 

在XML助手:

internal static class XmlHelper 
{ 
    internal static void WriteShallowNode(XmlReader reader, XmlWriter writer) 
    { 
     if (reader == null) 
     { 
      throw new ArgumentNullException("reader"); 
     } 
     if (writer == null) 
     { 
      throw new ArgumentNullException("writer"); 
     } 

     switch (reader.NodeType) 
     { 
      case XmlNodeType.Element: 
       writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI); 
       writer.WriteAttributes(reader, true); 
       if (reader.IsEmptyElement) 
       { 
        writer.WriteEndElement(); 
       } 
       break; 
      case XmlNodeType.Text: 
       writer.WriteString(reader.Value); 
       break; 
      case XmlNodeType.Whitespace: 
      case XmlNodeType.SignificantWhitespace: 
       writer.WriteWhitespace(reader.Value); 
       break; 
      case XmlNodeType.CDATA: 
       writer.WriteCData(reader.Value); 
       break; 
      case XmlNodeType.EntityReference: 
       writer.WriteEntityRef(reader.Name); 
       break; 
      case XmlNodeType.XmlDeclaration: 
      case XmlNodeType.ProcessingInstruction: 
       writer.WriteProcessingInstruction(reader.Name, reader.Value); 
       break; 
      case XmlNodeType.DocumentType: 
       writer.WriteDocType(reader.Name, reader.GetAttribute("PUBLIC"), reader.GetAttribute("SYSTEM"), 
        reader.Value); 
       break; 
      case XmlNodeType.Comment: 
       writer.WriteComment(reader.Value); 
       break; 
      case XmlNodeType.EndElement: 
       writer.WriteFullEndElement(); 
       break; 
     } 
    } 
}