c# - 开始使用带有证书身份验证的 WCF 路由 - 陷入 XML hell

标签 c# wcf wcf-routing

我有一个简单的 WCF 客户端 -> 服务器结构,其中客户端引用服务器的 WCF 服务。身份验证是使用 X509 证书完成的。

我想为我的服务添加一种简单形式的冗余。意思是让多个服务器运行,并让客户端使用一个路由器,如果主服务器坏了,它会透明地故障转移到备用服务器。
简单吧?

我使用了 hello world示例代码,只是将我的路由器的 app.config 文件更改为类似于我的客户端的文件。
然后我将我的客户端指向路由器。

我付出努力得到的唯一返回是一个不安全或不正确保护的故障异常,内部异常说:
无法处理消息。这很可能是因为“http://www.MyCompany.com/MyApp/api/IMyCompanyMyAppService/GetItems”操作不正确,或者因为消息包含无效或过期的安全上下文 token ,或者因为绑定(bind)之间存在不匹配。如果服务由于不活动而中止 channel ,则安全上下文 token 将无效。为防止服务过早中止空闲 session ,增加服务端点绑定(bind)的接收超时。

显然,所有这些原因都是公然的谎言(GetItems 方法 已实现,绑定(bind)没有不匹配,因为我从我的客户端配置中复制粘贴了它们,我的接收超时没有问题)。

现在我不知所措;我有一种预感,这可能与我使用的身份验证方法(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>

最佳答案

嗯,目前看来没有解决办法;
似乎 WCF 只支持 windows 凭据方法(参见 here)。
所以它回到了绘图板......如果有人感兴趣 - this是我进去的方向。

关于c# - 开始使用带有证书身份验证的 WCF 路由 - 陷入 XML hell ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10121906/

相关文章:

c# - 检查用户是否在 Orchard CMS 中获得授权

c# 是否可以在需要接口(interface)时提供 lambda?

c# - 失去焦点时关闭弹出窗口

具有 WCF 数据的 WPF 应用程序 - EF、Linq2Sql 或 WCF 数据服务 - 无似乎 'Easy'

c# - 避免在目录中一次更改太多错误

c# - W3C (IIS) 日志记录不记录我的 WCF 服务的 ClaimsIdentity 用户名

wcf - System.ServiceModel.ClientBase 连接到服务

c# - 组合/聚合许多底层服务响应的 WCF 路由器

c# - 我怎样才能让 WCF 路由给我一个比没有匹配的 MessageFilter 更详细的错误消息?

WCF 路由 + SSL