Клиент WCF - Как обработать или игнорировать элемент заголовка MustUnderstand? - PullRequest
6 голосов
/ 28 марта 2012

Я пишу WCF клиент, который использует веб-сервис не-Net, используя WS-Security. Ответ службы содержит заголовок Security с значением mustUnderstand, равным true.

Используя ServiceModelListener, я вижу фактические данные, возвращаемые из службы. Однако клиент WCF не работает, поскольку он не обрабатывает заголовок безопасности.

<env:Header>
<wsse:Security env:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Timestamp wsu:Id="timestamp">
<wsu:Created>2012-03-28T13:43:54.474Z</wsu:Created>
<wsu:Expires>2012-03-28T13:48:54.474Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</env:Header>

Сообщение об ошибке клиента WCF:

Заголовок 'Security' из пространства имен 'http://docs.oasis -open.org / wss / 2004/01 / oasis-200401-wss-wssecurity-secext-1.0.xsd ' не был понят получатель этого сообщения, в результате чего сообщение не будет обработано. Эта ошибка обычно указывает, что отправитель этого сообщения включил протокол связи, который получатель не может обработать. Пожалуйста, убедитесь, что конфигурация привязки клиента соответствует привязке службы.

Мой WCF клиент не нуждается ни в какой информации о отметке времени. Есть ли простой способ заглушки в процессе обработки? Я уже пытался расширить класс Response и добавить свойство [MessageHeader].

EDIT:

Спрашивается другой способ: как реализовать клиент WCF, который принимает пользовательские элементы заголовка, помеченные как Must Understand?

Ответы [ 2 ]

3 голосов
/ 25 мая 2012

Я столкнулся с подобной проблемой.Я не уверен, является ли это полезным или нет.

MSDN WCF Расширяемость

http://blogs.msdn.com/b/carlosfigueira/archive/2011/04/19/wcf-extensibility-message-inspectors.aspx

Настройка здесь основана на сертификатах, Oracle Application Server 10g и .Netпотреблять услуги.Использование SOAPUi было очень полезно при попытке выяснить, что происходит с запросом, а затем с ответом.

Я не пытался изменить код для использования basicHttpBinding, но я использовал WSHttpBinding в качестве основы моей конфигурации в коде.,Затем использовал

 WSHttpBinding binding = new WSHttpBinding()
        {
            CloseTimeout = new TimeSpan(0, 1, 0),
            OpenTimeout = new TimeSpan(0, 1, 0),
            SendTimeout = new TimeSpan(0, 1, 0),
            AllowCookies = false,
            BypassProxyOnLocal = false,
            HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
            MaxBufferPoolSize = 524288,
            MaxReceivedMessageSize = 65536,
            MessageEncoding = WSMessageEncoding.Text,
            UseDefaultWebProxy = false,
            ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
            {
                MaxDepth = 32,
                MaxArrayLength = 16384,
                MaxBytesPerRead = 4096,
                MaxNameTableCharCount = 16384,
                MaxStringContentLength = 8192
            }
        };
        binding.Security.Mode = SecurityMode.Transport;
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
        binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
        binding.Security.Transport.Realm = string.Empty;
        binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
        binding.Security.Message.EstablishSecurityContext = true;
        binding.Security.Message.NegotiateServiceCredential = true;

        CustomBinding customBinding = new CustomBinding();
        BindingElementCollection collection = binding.CreateBindingElements();

Проход по циклу для TextMessageEncodingBindingElement, чтобы установить Soap11 и AddressingVersion в None.

 foreach (BindingElement element in collection)
        {
            if (typeof(TextMessageEncodingBindingElement) == element.GetType())
            {
                TextMessageEncodingBindingElement item = element as TextMessageEncodingBindingElement;
                if (null != item)
                {
                    item.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap11, AddressingVersion.None);
                    customBinding.Elements.Add(item);
                }
            }
            else
                customBinding.Elements.Add(element);
        }

Я использовал ChannelFactory и добавил поведение EndPoint для инспектора сообщений.В этот момент у меня был контроль над запросом, и я мог добавить соответствующий заголовок и изменить mustUnderstand в действии.

Используя SOAPUi, я взял Message.ToString () и поместил его в SOAPUI и протестировал запрос,Как только необходимые элементы были добавлены в запрос, было определено, что сервер OAS не отвечает всеми необходимыми элементами.Используя инспектор сообщений для ответа, я изменил сообщение, добавив отсутствующие заголовки.Я не могу вспомнить, где я нашел базовый код для инспектора сообщений, но вам нужно изменить свой код, чтобы правильно его отобразить.

Для моего примера вот несколько фрагментов.

Длясообщение преобразования в

 public object BeforeSendRequest

Мне нужно было изменить заголовок, поэтому, используя цикл for, я взял XElement, добавил заголовок OASIS и добавил заголовок To.

XNamespace xmlns = "http://schemas.xmlsoap.org/soap/envelope/";
                XElement securityHeader = new XElement(
                    xmlns + "Security", 
                    new XAttribute(xmlns + "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"), 
                    new XAttribute(xmlns + "xmlns", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"), 
                    new XAttribute(xmlns + "mustUnderstand", "0"));
                element.Add(securityHeader);

Iтакже пришлось изменить заголовок действия

 else if (localName.Equals("Action", StringComparison.InvariantCultureIgnoreCase))
            {
                foreach (XAttribute a in element.Attributes())
                {
                    if (a.Name.LocalName == "mustUnderstand")
                        a.Value = "0";
                }
            }

Моя проблема заключалась в том, что служба не ответила заголовком действия

Так что в

 public void AfterReceiveReply

я позвонилмой TransformReply возвращает тип сообщения с чем-то вроде следующего.Вам может потребоваться изменить значения для строки. Пусто, но это только пример.

...

 Message reply = Message.CreateMessage(message.Version, null, reader);
        reply.Headers.Add(MessageHeader.CreateHeader("Action", string.Empty, string.Empty, false));
        reply.Properties.CopyProperties(message.Properties);

...

Я бы действительно предложилиспользуя такой инструмент, как SOUPUI, можно связываться с конвертом и видеть ответ.Если вы используете SSL, вам нужно создать файл cacert и поместить его в настройки SSLS настроек.

1 голос
/ 28 марта 2012

Существуют разные стандарты WS-Security. Возможно, имеет смысл изменить привязку на стороне клиента, поскольку basicHttpBinding и wsHttpBindings работают с различными стандартами безопасности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...