Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有相互SSL(在服务和客户端之间)的自托管WCF服务失败,403被禁止_Wcf_Ssl_Https_Mutual Authentication - Fatal编程技术网

具有相互SSL(在服务和客户端之间)的自托管WCF服务失败,403被禁止

具有相互SSL(在服务和客户端之间)的自托管WCF服务失败,403被禁止,wcf,ssl,https,mutual-authentication,Wcf,Ssl,Https,Mutual Authentication,我正在尝试在一个自托管WCF服务和一个客户端应用程序(现在是命令提示符)之间设置一个相互SSL的演示。最后,我试图找到一个解决方案,在使用证书进行传入连接的服务器和多个客户端(每个客户端都有单独的证书,我可以使用这些证书唯一地标识每个客户端)之间具有传输安全性(而不是消息安全性) 我尝试了许多不同的方法,但都没有成功(我无法找到一个确切的例子来说明我一直在尝试做的事情)。每次我想我接近时,当我试图调用服务时,客户端就会出现一个异常。我遇到的最常见的异常是: “The HTTP request w

我正在尝试在一个自托管WCF服务和一个客户端应用程序(现在是命令提示符)之间设置一个相互SSL的演示。最后,我试图找到一个解决方案,在使用证书进行传入连接的服务器和多个客户端(每个客户端都有单独的证书,我可以使用这些证书唯一地标识每个客户端)之间具有传输安全性(而不是消息安全性)

我尝试了许多不同的方法,但都没有成功(我无法找到一个确切的例子来说明我一直在尝试做的事情)。每次我想我接近时,当我试图调用服务时,客户端就会出现一个异常。我遇到的最常见的异常是:

“The HTTP request was forbidden with client authentication scheme 'Anonymous'.”
Inner exception: "The remote server returned an error: (403) Forbidden."
是否有人对我可能做错了什么有任何想法,或者对如何在上述场景中设置相互SSL有更好的了解

完全公开-现在我正在同一台计算机上运行客户端和服务器。不知道这是否重要

下面是配置代码段

服务和客户机代码相对来说很简单,所以我很有信心我已经让它们工作了。应用程序的配置(特别是绑定和行为)和证书“更有趣”,因此我对此没有信心

我如何创建证书(实际命令逐字)

将证书与端口关联(实际命令逐字)

服务器设置

绑定:

  <wsHttpBinding>
    <binding name="CustomBinding">      
      <security mode="Transport">
        <transport clientCredentialType="Certificate"/>
      </security>
    </binding>
  </wsHttpBinding>
  <wsHttpBinding>
    <binding name="CustomBinding">      
      <security mode="Transport">
        <transport clientCredentialType="Certificate"/>
      </security>
    </binding>
  </wsHttpBinding>

行为:

    <serviceBehaviors>
      <behavior name="">
      <!--
      <serviceCredentials>
        <serviceCertificate
           findValue="system"
           storeLocation="LocalMachine"
           storeName="My"
           x509FindType="FindBySubjectName"/>
      </serviceCredentials>
      -->
      <serviceAuthorization
         serviceAuthorizationManagerType=
              "ClientAuthorization.ClientCertificateAuthorizationManager, Simulator.Service.SideA" />
    </behavior>
  </serviceBehaviors>

客户端

绑定:

  <wsHttpBinding>
    <binding name="CustomBinding">      
      <security mode="Transport">
        <transport clientCredentialType="Certificate"/>
      </security>
    </binding>
  </wsHttpBinding>
  <wsHttpBinding>
    <binding name="CustomBinding">      
      <security mode="Transport">
        <transport clientCredentialType="Certificate"/>
      </security>
    </binding>
  </wsHttpBinding>

行为

  <endpointBehaviors>
    <behavior name="ChannelManagerBehavior">
      <clientCredentials>
         <clientCertificate findValue="client1"
                           storeLocation="LocalMachine"
                           storeName="My"
                           x509FindType="FindBySubjectName" />
        <!--
        <serviceCertificate>
          <authentication certificateValidationMode="PeerOrChainTrust"/>
        </serviceCertificate>
        -->
      </clientCredentials>
     </behavior>
  </endpointBehaviors>

更新

因此,我在服务器上添加了一个自定义用户名和密码验证程序,试图覆盖默认行为,并且无论提供的凭据是什么,都始终允许(同样,我真的不希望用户名/密码验证)此验证程序从未被调用。客户端仍会收到“身份验证方案‘匿名’”异常

服务行为更新

  <serviceCredentials>
    <userNameAuthentication 
      userNamePasswordValidationMode="Custom"
      customUserNamePasswordValidatorType=
        "Service.ClientAuthorization.ClientUserNamePasswordValidatorManager, Service.SideA" />
  </serviceCredentials>

SSL握手必须成功完成,才能通过任何HTTP通信。您收到的HTTP响应表明您的SSL设置工作正常


403禁止响应表示服务器已设置为在提供资源/页面之前需要HTTP基本身份验证用户名和密码。除了在TLS/SSL级别正在执行的操作之外,您还需要客户端在HTTP级别提供基本身份验证用户名/密码,或者您需要设置服务器以允许访问没有HTTP基本身份验证。

以下是供您参考的演示。我在同一台机器上的win7+vs2010+客户端服务器下对其进行了测试

服务器端:

[ServiceContract(Name="CalculatorService")]
    public interface ICalculatorService {
        [OperationContract]
        int Add(int x, int y);
    }

public class CalculatorService : ICalculatorService {
        public Int32 Add(Int32 x, Int32 y) {
            Console.WriteLine("{0}: service method called (x = {1}, y = {2})",
                Thread.CurrentThread.ManagedThreadId, x, y);
            return x + y;
        }
    }

class Program {
        static void Main(string[] args) {
            ServicePointManager.ServerCertificateValidationCallback +=
                (sender, certificate, chain, sslPolicyErrors) => true;

            using (var serviceHost = new ServiceHost(typeof(CalculatorService))) {
                serviceHost.Opened += delegate {
                    Console.WriteLine("{0}: service started", 
                        Thread.CurrentThread.ManagedThreadId);
                };
                serviceHost.Open();
                Console.Read();
            }
        }
    }

<?xml version="1.0" encoding="utf-8" ?> <configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="transportSecurity">
                    <security mode="Transport">
                        <transport clientCredentialType="Certificate"/>
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>

        <services>
            <service name="WcfService.CalculatorService">
                <endpoint address="https://hp-laptop:3721/calculatorservice"
                          binding="wsHttpBinding"
                          bindingConfiguration="transportSecurity"
                          contract="Contract.ICalculatorService" />
            </service>
        </services>
    </system.serviceModel> </configuration>
[ServiceContract(Name=“CalculatorService”)]
公共接口iCalculator服务{
[经营合同]
整数加(整数x,整数y);
}
公共类计算器服务:ICalculatorService{
公共Int32添加(Int32 x,Int32 y){
WriteLine(“{0}:调用的服务方法(x={1},y={2})”,
Thread.CurrentThread.ManagedThreadId,x,y);
返回x+y;
}
}
班级计划{
静态void Main(字符串[]参数){
ServicePointManager.ServerCertificateValidationCallback+=
(发送方、证书、链、sslPolicyErrors)=>true;
使用(var serviceHost=newservicehost(typeof(CalculatorService))){
serviceHost.Opened+=委托{
Console.WriteLine(“{0}:服务已启动”,
Thread.CurrentThread.ManagedThreadId);
};
Open();
Console.Read();
}
}
}
客户端:

class Program {
        static void Main(string[] args) {
            using (var channelFactory =
                new ChannelFactory<ICalculatorService>("calculatorservice")) {
                ICalculatorService proxy = channelFactory.CreateChannel();
                Console.WriteLine(proxy.Add(1, 2));
                Console.Read();
            }
            Console.Read();
        }
    }

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="transportSecurity">
                    <security mode="Transport">
                        <transport clientCredentialType="Certificate"/>
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <behaviors>
            <endpointBehaviors>
                <behavior name="defaultClientCertificate">
                    <clientCredentials>
                        <clientCertificate 
                            storeLocation="LocalMachine" 
                            storeName="My" 
                            x509FindType="FindBySubjectName" 
                            findValue="client1"/>
                    </clientCredentials>
                </behavior>
            </endpointBehaviors>
        </behaviors>
        <client>
            <endpoint name="calculatorservice" behaviorConfiguration="defaultClientCertificate"
                      address="https://hp-laptop:3721/calculatorservice"
                      binding="wsHttpBinding"
                      bindingConfiguration="transportSecurity"
                      contract="Contract.ICalculatorService"/>
        </client>
    </system.serviceModel>
</configuration>
类程序{
静态void Main(字符串[]参数){
使用(var)通道工厂=
新通道工厂(“计算器服务”)){
ICalculatorService proxy=channelFactory.CreateChannel();
Console.WriteLine(proxy.Add(1,2));
Console.Read();
}
Console.Read();
}
}
证书创建:

自创CA

makecert-n“CN=RootCA”-r-sv c:\RootCA.pvk c:\RootCA.cer

创建后,通过证书控制台将此证书导入“受信任的根证书”。这是停止您提到的异常的步骤

服务项目证书

makecert-n“CN=hp笔记本电脑”-ic c:\rootca.cer-iv c:\rootca.pvk-sr LocalMachine-ss My-pe-sky交换

请注意,上面的CN值应与服务地址的DNS部分匹配。例如,hp laptop是我的计算机名。服务端点的地址将为“:/…”(由于某些stackoverflow规则,将google.com替换为“hp laptop”)

向服务计划注册服务证书:

netsh http add sslcert ipport=0.0.0.0:3721 证书哈希=‎6c78ad6480d62f5f460f17f70ef9660076872326 appid={a0327398-4069-4d2d-83c0-a0d5e6cc71b5}

certhash值是服务程序证书的指纹(使用证书控制台检查)。t
<serviceSecurityAudit auditLogLocation="Application"
            suppressAuditFailure="false" 
            serviceAuthorizationAuditLevel="SuccessOrFailure" 
            messageAuthenticationAuditLevel="SuccessOrFailure" />
   <clientCertificate>              <authentication certificateValidationMode="Custom" customCertificateValidatorType="App.Web.Framework.MyX509CertificateValidator, App.Vertical.Send"  />
   </clientCertificate>