Безопасность транспорта WCF, wsHttpBinding, безопасность сообщений в балансировщике нагрузки. - PullRequest
2 голосов
/ 18 января 2012

У меня есть служба WCF, которая использует безопасность сообщений через HTTPS, используя wsHttpBinding за балансировщиком нагрузки.Когда подключается к сервису через веб-браузер через https, он работает.Однако клиенту Windowns формы не удалось, с использованием сертификата через https,

Обновление

URL-адрес запроса - https, но после исключения, говорящего http, ниже приведена трассировка исключения на стороне сервера:

Например: URL-адрес запроса:

https: // www.server.com/wcf.svc'.

Но он становится

http: // www.server.com:81/wcf.svc 'на стороне сервера.Вызывает ли это балансировка нагрузки.

System.ServiceModel.EndpointNotFoundException, System.ServiceModel, версия = 3.0.0.0, Culture = нейтральный, PublicKeyToken = b77a5c561934e089

Не было ни одного канала, активно прослушивающего'http://www.server.com:81/wcf.svc'. Это часто вызывается неверным адресом URI.Убедитесь, что адрес, на который отправляется сообщение, совпадает с адресом, на котором служба прослушивает.

Ниже приведена конфигурация службы WCF:

<system.serviceModel>
    <diagnostics>
      <messageLogging logEntireMessage="true" logMalformedMessages="true"
              logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false" />
    </diagnostics>
    <services>
      <service behaviorConfiguration="verServiceBehaviour" name="ver.Service">

        <endpoint address="ver" binding="wsHttpBinding" bindingConfiguration="wshttpbindingcfg"             
                   contract="ver.Iver"  behaviorConfiguration ="verEndpointBehaviour">  
        </endpoint>

        <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="mexhttpbinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="https://www.server.com/" />
          </baseAddresses>
        </host>
      </service>   

    </services>
    <bindings>
      <mexHttpBinding>
        <binding name="mexhttpbinding" />
      </mexHttpBinding>
      <wsHttpBinding>
        <binding name="wshttpbindingcfg" maxReceivedMessageSize="2000000000" sendTimeout="00:10:00">
          <readerQuotas maxStringContentLength="2000000000"/>

          <reliableSession ordered="true" enabled="false" />

            <security mode="None">
                        <transport clientCredentialType="None" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Certificate" negotiateServiceCredential="true"
                            algorithmSuite="Default" establishSecurityContext="false" />
                    </security>

        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="verEndpointBehaviour">
          <instanceContextBehavior/>
          <verInspectorBehavior/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="verServiceBehaviour">
          <dataContractSerializer maxItemsInObjectGraph="100000000"/>
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />

          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck" trustedStoreLocation="LocalMachine" mapClientCertificateToWindowsAccount="false"/>
            </clientCertificate>

                <serviceCertificate
               x509FindType="FindByThumbprint"
               findValue="xxxx"
               storeLocation="LocalMachine"
               storeName="My"/>

          </serviceCredentials>

        </behavior>


      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

Ниже приведена конфигурация клиента:

<configuration>
    <appSettings>
        <add key="CertificateSubjectName" value="subjectName"/>
    </appSettings>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_ver.IverHTTPS" 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>
        <client>
            <endpoint address="https://www.server.com/wcf.svc" 
              binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ver.IverHTTPS"
              contract="ServiceReference.verIver" name="verEndPoint" />


        </client>
    </system.serviceModel>
</configuration>

ниже - код клиента с использованием сертификата:

var proxyClient = new ServiceReference.VerIVerClient("verEndPoint");

proxyClient.ClientCredentials.ClientCertificate.SetCertificate(
    System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser,
    System.Security.Cryptography.X509Certificates.StoreName.My,    
    System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName,
    subjectName");                   

proxyClient.CallService()

Ниже приведено исключение на стороне клиента:

System.ServiceModel.EndpointNotFoundException was unhandled
  Message=There was no endpoint listening at https://ver20.server.com/wcf.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
  Source=mscorlib
  StackTrace:
    Server stack trace: 
       at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
       at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
       at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at verClient.ServiceReference.verIver.GetClaimver(GetClaimverClaimApplication ClaimApplication)
       at verClient.ServiceReference.verIverClient.GetClaimver(GetClaimverClaimApplication ClaimApplication) in D:\Projects\ver\verClient\Service References\ServiceReference\Reference.cs:line 11330
       at verClient.verForm.PostXmlTover(GetClaimverClaimApplication ClaimApplication) in D:\Projects\ver\verClient\verForm.cs:line 1408
       at verClient.verForm.PostButton_Click(Object sender, EventArgs e) in D:\Projects\ver\verClient\verForm.cs:line 34
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at verClient.Program.Main() in D:\Projects\ver\verClient\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.Net.WebException
       Message=The remote server returned an error: (404) Not Found.
       Source=System
       StackTrace:
            at System.Net.HttpWebRequest.GetResponse()
            at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
       InnerException: 

1 Ответ

2 голосов
/ 24 июня 2012

Проверьте конфигурацию своего балансировщика нагрузки и убедитесь, что запросы направляются на правильный номер хоста и порта. Если выбранный вами номер порта не является стандартным, обязательно настройте привязку сайта IIS и базовый адрес вашей службы.

Одна важная вещь, которую нужно понять о транспортной безопасности, это то, что она должна быть настроена на основе «прыжка» и «прыжка». В вашем примере у вас есть два прыжка (клиент) -> (балансировщик нагрузки) и (балансировщик нагрузки) -> (сервер).

Защита вашего подключения от клиента к балансировщику нагрузки не приводит к автоматической настройке безопасности от балансировщика нагрузки до сервера. Вам необходимо установить и настроить ssl-сертификат на балансировщике нагрузки и на сервере.

Ваш первоначальный https-запрос оказался http-запросом на сервере, что является хорошим признаком того, что вы не настроили безопасный канал между балансировщиком нагрузки и сервером.

Если вы не хотите защищать соединение между балансировщиком нагрузки и сервером, тогда предоставьте свой сервис без защиты транспорта. При этом у вас все равно может быть связь от клиента к балансировщику нагрузки (первый переход) по ssl.

...