BizTalk SendPort WCF Вызов веб-службы.asmx с использованием WS-Security
Все, что я нашел до сих пор, говорит, что я должен иметь возможность использовать WCF для вызова веб-службы.asmx, которая использует WS-Security. Вопрос в том, как настроить WCF-порт. Я использую WCF-BasicHttp. Прежде всего, это хорошо? Во-вторых, как правильно ввести пользователя / пройти правильно. На вкладке "Безопасность" выбрать "Режим безопасности"?
Единственное, что позволяет мне вводить учетные данные - это TransportWithMessageCredential, затем я могу нажать кнопку "Изменить" по учетным данным и ввести имя пользователя / пароль.
Но когда я это сделал, я получил это:
<soap:Fault xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<faultcode xmlns:q0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">q0:Security</faultcode>
<faultstring>Microsoft.Web.Services3.Security.SecurityFault: Security requirements are not satisfied because the security header is not present in the incoming message.
at Microsoft.Web.Services3.Design.UsernameOverTransportAssertion.ServiceInputFilter.ValidateMessageSecurity(SoapEnvelope envelope, Security security)
at MSB.RCTExpress.Presentation.Web.UsernameOverTransportAssertion.ServiceInputFilter.ValidateMessageSecurity(SoapEnvelope envelope, Security security)
in C:\projects\la1safe1\RCT Express\MSB.RCTExpress\3.10\Presentation.Web\UsernameOverTransportNoSendNone.cs:line 27
at Microsoft.Web.Services3.Security.ReceiveSecurityFilter.ProcessMessage(SoapEnvelope envelope)
at Microsoft.Web.Services3.Pipeline.ProcessInputMessage(SoapEnvelope envelope)
at Microsoft.Web.Services3.WseProtocol.FilterRequest(SoapEnvelope requestEnvelope)
at Microsoft.Web.Services3.WseProtocol.RouteRequest(SoapServerMessage message)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)</faultstring>
<faultactor>http://rct3.msbexpress.net/demo/ExpressLync/ValuationService.asmx</faultactor>
</soap:Fault>
Есть идеи?
Спасибо,
Нил Уолтерс
Продолжение публикации TomasR - использование привязки WS-HTTP:
1) BizTalk "Мастер использования WCF" создает пользовательский файл привязки и файл привязки WS-BasicHTTP, поэтому я изменил SendPort и вручную скопировал все конфигурации.
Установите следующим образом:
Режим безопасности: сообщение
Тип учетных данных клиента сообщений: UseName
Algorithm Suite: Basic256 [я понятия не имел, что здесь поставить]
Я также установил два других флажка:
а) Согласовать учетные данные службы [если я не проверю это, он хочет "отпечаток"]
б) установить контекст безопасности [также пытался не проверять этот]
2) Побежал и получил эту ошибку:
Описание:
Адаптеру не удалось передать сообщение, идущее на отправку порта "WcfSendPort_ValuationServicePort_ValuationServicePortSoap" с URL-адресом " http://rct3.msbexpress.net/demo/ExpressLync/ValuationService.asmx". Он будет повторно передан после интервала повторения, указанного для этого порта отправки.
Подробности:"System.NullReferenceException: ссылка на объект не установлена для экземпляра объекта.
Трассировка стека сервера:
at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)
at System.ServiceModel.Security.SspiNegotiationTokenProvider.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.TlsnegoTokenProvider.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Security.CommunicationObjectSecurityTokenProvider.Open(TimeSpan timeout)
at System.ServiceModel.Security.SecurityUtils.OpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout)
at System.ServiceModel.Security.SymmetricSecurityProtocol.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.ClientSecurityChannel`1.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.DoOperation(SecuritySessionOperation operation,
EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout)
at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecuritySessionChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open()
Исключение переброшено в [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at System.ServiceModel.ICommunicationObject.Open()
at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient`2.GetChannel[TChannel](IBaseMessage bizTalkMessage,
ChannelFactory`1& cachedFactory)
at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient`2.SendMessage(IBaseMessage bizTalkMessage)".
Теперь попробовал пользовательское связывание, добавил user/pass и получил эту ошибку:
<soap:Fault xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Code>
<soap:Value xmlns:q0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">q0:Security</soap:Value>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">Microsoft.Web.Services3.Security.SecurityFault:
Security requirements are not satisfied because the security header is not present in the incoming message.
at Microsoft.Web.Services3.Design.UsernameOverTransportAssertion.ServiceInputFilter.ValidateMessageSecurity(SoapEnvelope envelope,
Security security)
at MSB.RCTExpress.Presentation.Web.UsernameOverTransportAssertion.ServiceInputFilter.ValidateMessageSecurity
(SoapEnvelope envelope, Security security) in
C:\projects\la1safe1\RCT Express\MSB.RCTExpress\3.10\Presentation.Web\UsernameOverTransportNoSendNone.cs:line 27
at Microsoft.Web.Services3.Security.ReceiveSecurityFilter.ProcessMessage(SoapEnvelope envelope)
at Microsoft.Web.Services3.Pipeline.ProcessInputMessage(SoapEnvelope envelope)
at Microsoft.Web.Services3.WseProtocol.FilterRequest(SoapEnvelope requestEnvelope)
at Microsoft.Web.Services3.WseProtocol.RouteRequest(SoapServerMessage message)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)</soap:Text>
</soap:Reason>
<soap:Node>http://rct3.msbexpress.net/demo/ExpressLync/ValuationService.asmx</soap:Node>
</soap:Fault>
Моя следующая попытка вернулась к WS-HTTP, но я попытался поместить User/Pass в назначение сообщения, а не в SendPort:
msgRCTGetRequest(SOAP.Username) = "myuser";
msgRCTGetRequest(SOAP.Password) = "mypass";
//msgRCTGetRequest(SOAP.UseSoap12) = true;
В результате этой ошибки:
<soap:Fault xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Code>
<soap:Value>soap:Sender</soap:Value>
</soap:Code><soap:Reason>
<soap:Text xml:lang="en">System.Web.Services.Protocols.SoapHeaderException: WSE012: The input was not a valid SOAP message because the following information is missing: action.
at Microsoft.Web.Services3.Utilities.AspNetHelper.SetDefaultAddressingProperties(SoapContext context, HttpContext httpContext)
at Microsoft.Web.Services3.WseProtocol.CreateRequestSoapContext(SoapEnvelope requestEnvelope)
at Microsoft.Web.Services3.WseProtocol.FilterRequest(SoapEnvelope requestEnvelope)
at Microsoft.Web.Services3.WseProtocol.RouteRequest(SoapServerMessage message)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)</soap:Text>
</soap:Reason>
</soap:Fault>
Пятая попытка, собирающаяся сдаться и открыть билет Microsoft:
msgRCTGetRequest(WCF.UserName) = "myuser";
msgRCTGetRequest(WCF.Password) = "mypass";
msgRCTGetRequest(WCF.Action) = "GetPropertyInfoSourceRecordPolicyNum";
msgRCTGetRequest(SOAP.MethodName) = "GetPropertyInfoSourceRecordPolicyNum";
msgRCTGetRequest(SOAP.Username) = "myuser";
msgRCTGetRequest(SOAP.Password) = "mypass";
та же ошибка, что и в четвертой попытке.
Согласно документу поставщика, предоставляющего веб-сервис, я должен поместить пользователя в элемент W-Security UsernameToken, пароль в WS-Security password и установить атрибут элемента в "PasswordDigest". В нем также говорится: "Этот токен должен быть добавлен в запрос SOAP для веб-метода". Я не уверен, как это переводится со старых дней WSE3 на новые дни WCF.
3 ответа
Используйте настраиваемое связывание, и из порта отправки BizTalk нажмите "Настроить", затем перейдите на крайнюю правую вкладку с надписью "Импорт / Экспорт". Вставьте следующий XML-файл в файл (sample.config) и затем импортируйте его в порт конфигурации. Это в основном экономит время ввода большого количества материала на вкладке привязки.
<configuration>
<system.serviceModel>
<client>
<endpoint
address="http://rct3.msbexpress.net/demo/ExpressLync/ValuationService.asmx"
binding="customBinding"
bindingConfiguration="ValuationServicePortSoap12"
contract="BizTalk"
name="WcfSendPort_ValuationServicePort_ValuationServicePortSoap12"/>
</client>
<bindings>
<customBinding>
<binding name="ValuationServicePortSoap12">
<security authenticationMode="UserNameOverTransport"
messageProtectionOrder="SignBeforeEncrypt"
includeTimestamp="true"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireDerivedKeys="false"
requireSignatureConfirmation="false"/>
<textMessageEncoding messageVersion="Soap11WSAddressingAugust2004"/>
<httpsTransport />
</binding>
</customBinding>
</bindings>
</system.serviceModel>
</configuration>
Выше не очень интуитивно понятно (я все еще жду ссылку от Microsoft, которая описывает это более подробно).
Затем вы все равно указываете пользователя / пароль на вкладке учетных данных.
Однако это вызвало у нас проблему, поскольку в веб-службе поставщика.asmx, которую мы вызывали, для IIS не было установлено значение "требует SSL". По-видимому, это требование для работы с WCF. Другими словами, он прекрасно работает с WSE3, вызывающим.NET к.NET, но при попытке вызвать WCF к.asmx к WCF предъявляется несколько более жесткое требование.
Нил Уолтерс
Нил, для WS-Security вам нужно использовать привязку / адаптер WCF-WsHttp. WCF-BasicHttp предназначен только для более простых сценариев, где протоколы WS-* не нужны.
.NET 4.0 и.NET 3.5 SP1 с исправлением 971831 позволяют WS-Security через транспорт http. Попробуйте использовать этот пример привязки:
<customBinding>
<binding name="httpAndWSSecurity">
<security authenticationMode="UserNameOverTransport"
allowInsecureTransport="true"/>
<textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />
<httpTransport/>
</binding>
Также см. Эту статью MSDN на SecurityBindingElement.AllowInsecureTransport