2017-04-27 78 views
1

我有一個WCF服務主機和預先配置的消息檢查器,通過XSD架構和整體消息大小驗證消息。這是它的實現。WCF消息檢查器錯誤與Kerberos身份驗證

public class SimpleMessageInspector : IDispatchMessageInspector 
{ 
    private AsyncAPISender _messageSender = new AsyncAPISender(); 
    private ILog logger = LogManager.GetLogger(typeof(SimpleMessageInspector)); 
    private readonly XmlSchemaSet _schemas; 
    // Max packet syze 50 Mb by default 
    private const int MaxPacketSizeByDefault = 52428800; 

    //Other methods of IDispatchMessageInspector 

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
    { 
     logger.DebugFormat("Recieved SOAP message: {0}", request); 

     var mb = request.CreateBufferedCopy(int.MaxValue); 

     request = mb.CreateMessage(); 
     var copyForValidation = mb.CreateMessage(); 
     var copyForCheckSize = mb.CreateMessage(); 

     ValidateMessage(ref copyForValidation); 

     CheckMessageSize(mb, ref copyForCheckSize); 

     return null; 
    } 

    void ValidateMessage(ref System.ServiceModel.Channels.Message message) 
    { 
     XmlDocument bodyDoc = new XmlDocument(); 
     bodyDoc.Load(message.GetReaderAtBodyContents().ReadSubtree()); 
     XmlReaderSettings settings = new XmlReaderSettings(); 
     settings.Schemas.Add(_schemas); 
     settings.ValidationType = ValidationType.Schema; 
     XmlReader r = XmlReader.Create(new XmlNodeReader(bodyDoc), settings); 

     try 
     { 
      while (r.Read()) { } 
     } 
     catch (Exception e) 
     { 
      throw new ArgumentException("Error on validation by xsd schema", e); 
     } 
    } 

    private void CheckMessageSize(MessageBuffer buffer, ref Message message) 
    { 
     int maxPacketSize; 
     var maxPacketSizeFromConfig = ConfigurationManager.AppSettings["MaxPacketSize"]; 
     if (!Int32.TryParse(maxPacketSizeFromConfig, out maxPacketSize)) 
     { 
      maxPacketSize = MaxPacketSizeByDefault; 
     } 

     if (buffer.BufferSize > maxPacketSize) 
     { 
      var messageInfo = GetMessageInfoType(ref message); 
      if (messageInfo != null) 
       _messageSender.CreateResultTask(messageInfo, null, "Max message size exceeded", false); 

      throw new Exception("Max message size exceeded"); 
     } 
    } 
} 

當主機臨危消息我有一個例外「因爲它已經被閱讀了此消息不支持操作」時,主機使用Kerberos結合與basicHttp一切正常,只heppens。這是導致錯誤的綁定配置。

<binding name="customKerberosBinding"> 
    <security authenticationMode="Kerberos" allowInsecureTransport="true" enableUnsecuredResponse="false" requireDerivedKeys="false" protectTokens="false" requireSignatureConfirmation="false" messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"></security> 
    <textMessageEncoding messageVersion="Soap11"></textMessageEncoding> 
      <httpTransport maxReceivedMessageSize="2000000000"></httpTransport> 
</binding> 

有什麼解釋爲什麼只發生在kerberos綁定和可能的解決方案?

回答

0

根據我使用IDispatchMessageInspector的經驗,您只能閱讀一次該消息。由於你閱讀它,並通過引用傳遞,我認爲這就是爲什麼你得到這個錯誤。在我進行驗證之後,在我的ValidateMessage方法中,創建了一條消息並將其返回。

object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext) 
{ 
    if (validateRequest) 
    { 
     if (!request.IsEmpty && !request.IsFault) 
     { 
      request = ValidateRequestMessageBody(request); 
      channel.Close(); 
      channel.Dispose(); 
     } 
    } 
    return null; 
} 

private Message ValidateRequestMessageBody(System.ServiceModel.Channels.Message message) 
{ 
    //do stuff 
    var reader = XmlReader.Create(memStream, settings);       
    var newMessage = Message.CreateMessage(reader, int.MaxValue, message.Version); 
    newMessage.Headers.Clear(); 
    newMessage.Headers.CopyHeadersFrom(message.Headers); 
    return newMessage; 
}