{error: (403) Forbidden. "} WCF basicHttpBinding с транспортными данными и сертификатом - PullRequest
0 голосов
/ 13 ноября 2018

Я получаю сообщение об ошибке "{" Удаленный сервер возвратил ошибку: (403) Запрещено. "} HTTP-запрос был запрещен в схеме аутентификации клиента« Аноним »." при использовании basicHttpBinding с безопасностью транспорта и учетными данными сертификата. Мой сервис находится в экземпляре amazon ec2, и мое клиентское приложение удаленно подключается к нему через Интернет. Я могу подключиться к службе wcf, если для моих учетных данных транспорта установлено значение «Нет» как в файле web.config службы, так и в app.config клиента. Мой сервисный сертификат похож на "www.example.com", установленный на amazon ec2 "Локальный магазин компьютеров" и "Личная папка". Мой сертификат клиентского приложения - это просто самозаверяющий сертификат, который я установил на его «локальную машину и личную папку», а также в «Хранилище доверенных лиц» в экземпляре amazon ec2, где находится моя служба wcf. Я также настроил «https» для моих привязок сайта IIS, и я могу попасть на сайт через «https://www.example.com"

».

Ниже приведен файл web.config, app.config и код, который имеется в клиентском приложении.

Сервис Web.config:

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <customErrors mode="Off"/>
  </system.web>
  <system.serviceModel>

   <bindings>
      <basicHttpBinding>
        <binding name="basicHttpBinding_Config" >
          <security mode="Transport">
            <transport clientCredentialType="Certificate"/>
          </security>
        </binding>        
      </basicHttpBinding>
  </bindings>

    <services>    
      <service name="MyProject.MyService">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpBinding_Config"
          contract="MyService"  />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>          
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust" trustedStoreLocation="LocalMachine"/>
            </clientCertificate>
            <serviceCertificate findValue="www.example.com" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" />
          </serviceCredentials>          
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>

Клиентский app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>                   

      <bindings>
        <basicHttpBinding>
          <binding name="basicHttpBinding_Config" >
            <security mode="Transport">
              <transport clientCredentialType="Certificate"/>
            </security>
          </binding>
        </basicHttpBinding>
      </bindings>
      <client>
        <endpoint address="https://www.example.com/sub/Service1.svc"
          binding="basicHttpBinding" bindingConfiguration="basicHttpBinding_Config"
          contract="ServiceReference1.MyService" name="BasicHttpBinding_MyService" />
      </client>

      <behaviors>
        <endpointBehaviors>
          <behavior>
            <clientCredentials>
              <clientCertificate findValue="clientKey"
                                 storeLocation="LocalMachine"
                                 storeName="My"
                                 x509FindType="FindBySubjectName" />
            </clientCredentials>

          </behavior>
        </endpointBehaviors>
      </behaviors>

    </system.serviceModel>
</configuration>

Код консоли клиентского приложения:

static void Main(string[] args)
        {
            System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate { return true; }; 

            ServiceReference1.MyServiceClient client = new ServiceReference1.MyServiceClient();
            string[] a = client.GetMethods(ref mh);
            foreach (string s in a)
            {
                Console.WriteLine(s);
            }
            Console.ReadKey();

        }

Диагностическая трассировка возвращается ниже:

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>131077</EventID>
<Type>3</Type>
<SubType Name="Critical">0</SubType>
<Level>1</Level>
<TimeCreated SystemTime="2018-11-16T21:50:58.8220239Z" />
<Source Name="System.ServiceModel" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="ConsoleApplication1" ProcessID="22220" ThreadID="1" />
<Channel />
<Computer>DESKTOP-RPNI11M</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical">
<TraceIdentifier>UnhandledException</TraceIdentifier>
<Description>Unhandled exception</Description>
<AppDomain>ConsoleApplication1.exe</AppDomain>
<Exception>
<ExceptionType>System.ServiceModel.Security.MessageSecurityException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The HTTP request was forbidden with client authentication scheme 'Anonymous'.</Message>
<StackTrace>
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory`1 factory)
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory`1 factory, WebException responseException, ChannelBinding channelBinding)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.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&amp; msgData, Int32 type)
at ConsoleApplication1.ServiceReference1.IOD_V416.GetMethods(GetMethodsRequest request)
at ConsoleApplication1.ServiceReference1.OD_V416Client.ConsoleApplication1.ServiceReference1.IOD_V416.GetMethods(GetMethodsRequest request) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Service References\ServiceReference1\Reference.cs:line 72017
at ConsoleApplication1.ServiceReference1.OD_V416Client.GetMethods(MultiSpeakMsgHeader&amp; MultiSpeakMsgHeader) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Service References\ServiceReference1\Reference.cs:line 72023
at ConsoleApplication1.Program.Main(String[] args) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Program.cs:line 43
</StackTrace>
<ExceptionString>System.ServiceModel.Security.MessageSecurityException: The HTTP request was forbidden with client authentication scheme 'Anonymous'. ---&gt; System.Net.WebException: The remote server returned an error: (403) Forbidden.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---

Server stack trace: 
   at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory`1 factory)
   at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory`1 factory, WebException responseException, ChannelBinding channelBinding)
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.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&amp; msgData, Int32 type)
   at ConsoleApplication1.ServiceReference1.IOD_V416.GetMethods(GetMethodsRequest request)
   at ConsoleApplication1.ServiceReference1.OD_V416Client.ConsoleApplication1.ServiceReference1.IOD_V416.GetMethods(GetMethodsRequest request) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Service References\ServiceReference1\Reference.cs:line 72017
   at ConsoleApplication1.ServiceReference1.OD_V416Client.GetMethods(MultiSpeakMsgHeader&amp; MultiSpeakMsgHeader) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Service References\ServiceReference1\Reference.cs:line 72023
   at ConsoleApplication1.Program.Main(String[] args) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Program.cs:line 43</ExceptionString>
<InnerException>
<ExceptionType>System.Net.WebException, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The remote server returned an error: (403) Forbidden.</Message>
<StackTrace>
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
</StackTrace>
<ExceptionString>System.Net.WebException: The remote server returned an error: (403) Forbidden.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)</ExceptionString>
</InnerException>
</Exception>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>

Я обращал внимание на другие подобные проблемы, но еще ни одна не решила, я постоянно ищу правильные решения, я ценю любую помощь или совет, который предоставляет сообщество.

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Я нашел следующее решение, которое работает для этой ошибки, с которой я столкнулся.

Сначала я создал сертификат следующим образом:

makecert -n "CN = MyRootSigningKey" -r -sv MyRootSigningKey.pvk MyRootSigningKey.cer

Во-вторых, я рассматриваю это как мой корневой ключ и устанавливаю его в моей службе AWS в хранилище сертификатов «Доверенные корневые центры сертификации», используя mmc.

В-третьих, я создалсамозаверяющий сертификат с использованием корневого ключа «MyRootSigningKey» следующим образом:

makecert -sk MySignedKeyName -iv MyRootSigningKey.pvk -n "CN = MySignedKey" -ic MyRootSigningKey.cer -sr localmachine -ss my -skyexchange -pe

Наконец, я ссылаюсь на самоподписанный сертификат "MySignedKey" в конфигурации моего клиентского приложения, как показано ниже:

<client>        
        <endpoint address="https://www.example.com/sub/Service1.svc" behaviorConfiguration="clientBehavior"
          binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_MyService"
          contract="ServiceReference1.MyService"  />

      </client>

      <behaviors>
        <endpointBehaviors>
          <behavior name="clientBehavior">
            <clientCredentials>
              <clientCertificate findValue="MySignedKey"
                                 storeLocation="LocalMachine"
                                 storeName="My"
                                 x509FindType="FindBySubjectName" />
            </clientCredentials>

          </behavior>
        </endpointBehaviors>
      </behaviors>
0 голосов
/ 14 ноября 2018

РЕДАКТИРОВАТЬ:

Вероятно, лучше использовать сертификат sha2:

makecert -len 2048 -r -a sha256 -sv private.pvk -n CN=yoursubjectname cert.cer
pvk2pfx -spc cert.cer -pvk private.pvk -pfx out.pfx

Установите частный сертификат (.pfx) на хосте, установите его в приложении IIS и установите открытый сертификат на клиенте (.cer), который вам нужно будет установить как в личных, так и в доверенных хранилищах людей.

РЕДАКТИРОВАТЬ: Я думаю, вам также нужно дать вашему поведению имя в конфигурации хоста и клиента и назначить это поведение вашим конечным точкам.

Ведущий:

<behavior name="serviceBahavior"> 
<service name="MyProject.MyService" behaviorConfiguration="serviceBahavior">

Клиент:

<behavior name="clientBahavior">
<endpoint address="https://www.example.com/sub/Service1.svc"
          binding="basicHttpBinding" bindingConfiguration="basicHttpBinding_Config"
          contract="ServiceReference1.MyService" name="BasicHttpBinding_MyService" behaviorConfiguration="clientBahavior" />

Я думаю, что поскольку вы используете <security mode="Transport">, вам нужно сделать свой мекс как HTTPS:

 <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />

Также установите в своем поведении службу метаданных

из: <serviceMetadata httpGetEnabled="true"/>

до <serviceMetadata httpsGetEnabled="true"/>

Кроме того, убедитесь, что ваш транспорт в конфигурации клиента соответствует конфигурации хоста:

<transport clientCredentialType="Certificate"/>

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