{错误:(403)禁止。”} WCF basicHttpBinding,带有传输和证书凭据

时间:2018-11-13 14:43:29

标签: wcf basichttpbinding

我收到错误“ {”,远程服务器返回错误:(403)禁止。”}使用客户端身份验证方案“匿名”禁止了HTTP请求。当将basicHttpBinding与传输安全性和证书凭据一起使用时。我的服务位于Amazon ec2实例中,我的客户端应用程序通过Internet远程连接到它。如果在服务的web.config和客户端的app.config中都将“传输”凭据设置为“无”,则可以连接到wcf服务。我的服务证书就像“ www.example.com”,已安装在Amazon ec2“本地计算机存储”和“个人文件夹”上。我的客户端应用程序证书只是一个自签名证书,我将其安装到其wcf服务所在的Amazon ec2实例的“本地计算机和个人文件夹”以及“受信任的人存储”中。我还为IIS网站绑定设置了“ https”,并且可以通过“ 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 :(得分:0)

编辑:

使用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">,因此您需要将mex设置为HTTPS:

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

还在您的行为中设置serviceMetadata

来自: <serviceMetadata httpGetEnabled="true"/>

<serviceMetadata httpsGetEnabled="true"/>

此外,请确保您在客户端配置中的传输与主机配置相匹配:

<transport clientCredentialType="Certificate"/>

答案 1 :(得分:0)

我发现以下解决方案可解决我遇到的此错误。

首先,我创建了如下证书:

makecert -n“ CN = MyRootSigningKey” -r -sv MyRootSigningKey.pvk MyRootSigningKey.cer

第二,我将此作为我的根密钥,并使用mmc将其安装在证书存储“受信任的根证书颁发机构”下的AWS服务中。

第三,我使用根密钥“ MyRootSigningKey”创建了一个自签名证书,如下所示:

makecert -sk MySignedKeyName -iv MyRootSigningKey.pvk -n“ CN = MySignedKey” -ic MyRootSigningKey.cer -sr localmachine -ss my -sky exchange -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>