Начало работы с маршрутизацией WCF с проверкой подлинности сертификата - застряло в аду XML
У меня есть простая структура WCF Client -> Server, где клиент ссылается на службу WCF сервера. Аутентификация выполняется с использованием сертификатов X509.
Я хочу добавить простую форму избыточности к моему сервису. это означает - иметь несколько работающих серверов, и клиент должен использовать маршрутизатор, который будет прозрачно переключаться на резервный сервер, если основной из них не работает.
Просто, правда?
Я использовал пример кода hello world и просто изменил файл app.config моего маршрутизатора, чтобы он стал похож на файл моего клиента.
Затем я указал своему клиенту на маршрутизатор.
Единственная награда, которую я получил за свои боли, была An insecured or incorrectly secured fault
исключение, с внутренним исключением, говорящим: The message could not be processed. This is most likely because the action 'http://www.MyCompany.com/MyApp/api/IMyCompanyMyAppService/GetItems' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.
Очевидно, что все эти причины - явная ложь (GetItems
метод реализован, привязка не является несоответствующей, так как я скопировал их из конфигурации моего клиента, и в моем тайм-ауте нет ничего плохого).
Теперь я в растерянности относительно того, что делать; У меня есть предчувствие, что это может быть связано с методом аутентификации, который я использую (сертификаты X509), но я действительно не имею понятия.
Прилагаются конфигурации для сервера, маршрутизатора и клиента.
<!--SERVER CONFIGURATION-->
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MyAppService_BasicHttpBindingConfigurationSSL"
maxBufferPoolSize="1073741824" maxBufferSize="1073741824" maxReceivedMessageSize="1073741824">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1073741824"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Basic" proxyCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="MyAppService_BindingConfiguration" maxBufferPoolSize="1073741824" maxReceivedMessageSize="1073741824">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1073741824"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Message">
<transport/>
<message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false"/>
</security>
</binding>
<binding name="MyAppService_BindingConfigurationOverSSL" maxBufferPoolSize="1073741824" maxReceivedMessageSize="1073741824">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1073741824"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportWithMessageCredential">
<transport/>
<message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="MyCompany.MyApp.MyAppService.Server.Service.MyCompanyMyAppService" behaviorConfiguration="MyAppService_Behavior">
<!-- Non-SSL endpoint -->
<endpoint name="MyAppServiceEndpoint"
address="http://localhost:8087/MyAppService"
binding="wsHttpBinding"
bindingNamespace="http://www.MyCompany.com/api/binding"
bindingConfiguration="MyAppService_BindingConfiguration"
behaviorConfiguration="WSDLBehavior"
contract="MyCompany.MyApp.MyAppService.Common.Services.IMyCompanyMyAppService"/>
<!-- SSL endpoint -->
<endpoint name="MyAppServiceEndpointSSL"
address="https://localhost:8088/MyAppService"
binding="wsHttpBinding"
bindingNamespace="http://www.MyCompany.com/api/binding"
bindingConfiguration="MyAppService_BindingConfigurationOverSSL"
behaviorConfiguration="WSDLBehavior"
contract="MyCompany.MyApp.MyAppService.Common.Services.IMyCompanyMyAppService"/>
<!--BasicHttpBinding-->
<!--SSL BasicHttpBinding -->
<endpoint name="MyAppServiceEndpointBasicSSL"
address="https://localhost:8088/MyAppServiceBasic"
bindingConfiguration="MyAppService_BasicHttpBindingConfigurationSSL"
binding="basicHttpBinding"
contract="MyCompany.MyApp.MyAppService.Common.Services.IMyCompanyMyAppService" />
<!-- Non-SSL Metadata endpoint -->
<endpoint name="MyAppServiceBinding" address="http://localhost:8087/mex" binding="mexHttpBinding" behaviorConfiguration="WSDLBehavior" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WSDLBehavior">
<!--<wsdlExtensions />-->
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyAppService_Behavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyCompany.MyApp.MyAppService.Server.Service.MyAppUsernamePasswordValidator, MyCompany.MyApp.MyAppService.Server" />
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck"/>
<certificate/>
</clientCertificate>
<serviceCertificate storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName" findValue="server.dev.MyApp.MyCompany.com"/>
</serviceCredentials>
<!-- Allow the service to handle a high load of calls and sessions -->
<serviceThrottling maxConcurrentCalls="300" maxConcurrentInstances="500" maxConcurrentSessions="30000"/>
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8087/mex" httpsGetEnabled="false" httpsGetUrl="https://localhost:8088/mex"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<!--ROUTER CONFIGURATION-->
<system.serviceModel>
<services>
<!--ROUTING SERVICE -->
<service behaviorConfiguration="routingData"
name="System.ServiceModel.Routing.RoutingService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/MyAppService"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
name="reqReplyEndpoint"
contract="System.ServiceModel.Routing.IRequestReplyRouter" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="MyAppServiceEndpointBasicSSL" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Basic" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="MyAppServiceEndpoint" maxBufferPoolSize="1073741824" maxReceivedMessageSize="1073741824">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1073741824"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Message">
<transport/>
<message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false"/>
</security>
</binding>
<binding name="MyAppServiceEndpointSSL" maxBufferPoolSize="1073741824" maxReceivedMessageSize="1073741824">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1073741824"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportWithMessageCredential">
<transport/>
<message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="routingData">
<serviceMetadata httpGetEnabled="True"/>
<routing filterTableName="routingTable1" />
</behavior>
</serviceBehaviors>
</behaviors>
<client>
<endpoint address="http://localhost:8087/MyAppService" binding="wsHttpBinding"
bindingConfiguration="MyAppServiceEndpoint" contract="MyCompanyMyAppService.IMyCompanyMyAppService"
name="MyAppServiceEndpoint">
<identity>
<certificate encodedValue="AwAAAAEAAAAUAAAAS2hv3zJGGxe4T0jo4fwcBgc2fbogAAAAAQAAABYCAAAwggISMIIBf6ADAgECAhDtT0KoiuHcoERR+GfWnIJJMAkGBSsOAwIdBQAwHzEdMBsGA1UEAxMUZGV2LmNybS5sZXZlcmF0ZS5jb20wHhcNMTExMTA5MDgyNDQ2WhcNMTMxMjMwMjIwMDAwWjAmMSQwIgYDVQQDExtzZXJ2ZXIuZGV2LmNybS5sZXZlcmF0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsBWu9R/c65MNdQRDkCi4w5uyxp4Hh5FK0hyUh9LzObQuSuMvqYc+cW1OuI1b4G1RBNOwGOzxUeK+dPX6Q5Y96qcmOk5+eJyPOg2dtHaOujGvaW1MN/sVJPMy6xgCtJ6iSe9xDYYmxcha2quZK3LGGvW3d3/QznBqY+XwK6kbHXAgMBAAGjUDBOMEwGA1UdAQRFMEOAEP3fipkit68H++sodJuSZSWhHTAbMRkwFwYDVQQDExBjcm0ubGV2ZXJhdGUuY29tghAluuQuFlNJpU+Yh7Yf725TMAkGBSsOAwIdBQADgYEAZVECKrndJdjMYnfSb2bCByv24mpgE2yCuhm2Ey+cSEwP31aKrHIVNAcVDPd7k1/R4qsWU6I8PHjVCeCHTMnf+EE/1IV0lbCj/PD/D3by+m/7hEKdtzk6VHJyJLmLyO6fIJc14XPI4qC/KVuUS97UjNpWcICZFgM64Vb7MUW5thE=" />
</identity>
</endpoint>
<endpoint address="https://localhost:8088/MyAppService" binding="wsHttpBinding"
bindingConfiguration="MyAppServiceEndpointSSL" contract="MyCompanyMyAppService.IMyCompanyMyAppService"
name="MyAppServiceEndpointSSL" />
<endpoint address="https://localhost:8088/MyAppServiceBasic" binding="basicHttpBinding"
bindingConfiguration="MyAppServiceEndpointBasicSSL" contract="MyCompanyMyAppService.IMyCompanyMyAppService"
name="MyAppServiceEndpointBasicSSL" />
</client>
<!--ROUTING SECTION -->
<routing>
<filters>
<filter name="MatchAllFilter1" filterType="MatchAll" />
</filters>
<filterTables>
<filterTable name="routingTable1">
<add filterName="MatchAllFilter1" endpointName="MyAppServiceEndpoint" />
</filterTable>
</filterTables>
</routing>
</system.serviceModel>
<!--CLIENT CONFIGURATION-->
<system.serviceModel>
<client>
<endpoint address="http://localhost:8087/MyAppService" binding="wsHttpBinding"
bindingConfiguration="MyAppServiceEndpoint" contract="MyCompanyMyAppService.IMyCompanyMyAppService"
name="MyAppServiceEndpoint">
<identity>
<certificate encodedValue="AwAAAAEAAAAUAAAAS2hv3zJGGxe4T0jo4fwcBgc2fbogAAAAAQAAABYCAAAwggISMIIBf6ADAgECAhDtT0KoiuHcoERR+GfWnIJJMAkGBSsOAwIdBQAwHzEdMBsGA1UEAxMUZGV2LmNybS5sZXZlcmF0ZS5jb20wHhcNMTExMTA5MDgyNDQ2WhcNMTMxMjMwMjIwMDAwWjAmMSQwIgYDVQQDExtzZXJ2ZXIuZGV2LmNybS5sZXZlcmF0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsBWu9R/c65MNdQRDkCi4w5uyxp4Hh5FK0hyUh9LzObQuSuMvqYc+cW1OuI1b4G1RBNOwGOzxUeK+dPX6Q5Y96qcmOk5+eJyPOg2dtHaOujGvaW1MN/sVJPMy6xgCtJ6iSe9xDYYmxcha2quZK3LGGvW3d3/QznBqY+XwK6kbHXAgMBAAGjUDBOMEwGA1UdAQRFMEOAEP3fipkit68H++sodJuSZSWhHTAbMRkwFwYDVQQDExBjcm0ubGV2ZXJhdGUuY29tghAluuQuFlNJpU+Yh7Yf725TMAkGBSsOAwIdBQADgYEAZVECKrndJdjMYnfSb2bCByv24mpgE2yCuhm2Ey+cSEwP31aKrHIVNAcVDPd7k1/R4qsWU6I8PHjVCeCHTMnf+EE/1IV0lbCj/PD/D3by+m/7hEKdtzk6VHJyJLmLyO6fIJc14XPI4qC/KVuUS97UjNpWcICZFgM64Vb7MUW5thE=" />
</identity>
</endpoint>
<endpoint address="https://localhost:8088/MyAppService" binding="wsHttpBinding"
bindingConfiguration="MyAppServiceEndpointSSL" contract="MyCompanyMyAppService.IMyCompanyMyAppService"
name="MyAppServiceEndpointSSL" />
<endpoint address="https://localhost:8088/MyAppServiceBasic" binding="basicHttpBinding"
bindingConfiguration="MyAppServiceEndpointBasicSSL" contract="MyCompanyMyAppService.IMyCompanyMyAppService"
name="MyAppServiceEndpointBasicSSL" />
</client>
<bindings>
<basicHttpBinding>
<binding name="MyAppServiceEndpointBasicSSL" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Basic" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="MyAppServiceEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" negotiateServiceCredential="false"
algorithmSuite="Default" establishSecurityContext="false" />
</security>
</binding>
<binding name="MyAppServiceEndpointSSL" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
1 ответ
Ну, похоже, на данный момент нет решения;
Похоже, что WCF поддерживает только метод учетных данных Windows (см. Здесь).
так что вернемся к чертежной доске... Если кому-то интересно - это направление, в котором я пошел.