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

我已经尝试了许多不同的方法,但没有一个有效(我无法找到一个确切的例子,我一直在尝试做)。 每次我认为我越来越近,当我尝试调用服务时,我最终会在客户端出现异常。 我遇到的最常见的例外是:

“The HTTP request was forbidden with client authentication scheme 'Anonymous'.”
Inner exception: "The remote server returned an error: (403) Forbidden."

有没有人对我可能做错了什么或者更好地了解如何在上述场景中设置相互SSL?

完全披露 - 截至目前,我在同一台计算机上运行客户端和服务器。 不确定是否重要。

下面的配置片段

服务和客户端代码相对微不足道,所以我非常有信心我已经让他们工作了。 应用程序配置(特别是绑定和行为)和证书“更有趣”,所以我不那么自信。

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

makecert -pe -n "CN=SelfSignedCA" -ss Root -sr LocalMachine  -a sha1 -sky signature -r -sv "SelfSignedCA.cer" "SelfSignedCA.pvk"
makecert -pe -n "CN=system" -ss my -sr LocalMachine -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1  -in "SelfSignedCA" -is Root -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 Service.cer
makecert -pe -n "CN=client1" -ss my -sr LocalMachine -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1  -in "SelfSignedCA" -is Root -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 Client1.cer

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

netsh http add urlacl url=https://+:44355/MyService/ user=EVERYONE

服务器设置

绑定:

  <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>

行为

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

UPDATE

因此,我向服务器添加了一个自定义用户名和密码验证器,试图覆盖默认行为,并始终允许无论提供的凭据(再次我真的不想要用户名/密码验证)。 永远不会调用此验证程序。 客户端仍然获得“身份验证方案'匿名'。”例外。

服务行为更新

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

===============>>#1 票数:3 已采纳

这是演示供您参考。 我在win7 + vs2010 + client-server-on-same-machine下测试了它。

服务器端:

[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>

客户端:

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>

证书创建:

自创CA.

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

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

服务计划证书

makecert -n“CN = hp-laptop”-ic c:\\ rootca.cer -iv c:\\ rootca.pvk -sr LocalMachine -ss My -pe -sky exchange

请注意,上面的CN值应与服务地址的DNS部分匹配。 例如,hp-laptop是我的电脑名称。 服务端点的地址为“ https://google.com:/ ...”。 (由于某些stackoverflow规则,用'hp-laptop'替换google dot com)。

使用服务程序注册服务证书:

netsh http add sslcert ipport = 0.0.0.0:3721 certhash = 6c78ad6480d62f5f460f17f70ef9660076872326 appid = {a0327398-4069-4d2d-83c0-a0d5e6cc71b5}

certhash值是服务程序证书的指纹(使用证书控制台检查)。 appid是服务程序文件“AssemblyINfo.cs”中的GUID。

客户计划认证:

makecert -n“CN = client1”-ic c:\\ rootca.cer -iv c:\\ rootca.pvk -sr LocalMachine -ss My -pe -sky exchange

更新:根据伤寒对此解决方案的经验,由于该服务器中有太多受信任的根权限,“匿名”例外仍然存在。 伤寒提供了两个链接来解决这个问题。

http://support.microsoft.com/kb/2464556

http://blog.codit.eu/post/2013/04/03/Troubleshooting-SSL-client-certificate-issue-on-IIS.aspx

===============>>#2 票数:3

另一个选择是监视实际的交换,包括ssl v3握手。 我碰到了类似的东西,最终发现SSL Handshake失败了,因为我有太多可信任的证书颁发机构。 要解决这个问题,我需要遵循这个决议 该解决方案使Windows的SSL部分不会将受信任的证书颁发机构发送回客户端; 因此,允许握手完成。

===============>>#3 票数:2

我有几天同样的问题,直到最后,我意识到这一行创建了“服务器身份验证”证书。 您需要“客户端身份验证”证书,否则客户端证书将被视为无效。

makecert -pe -n“CN = client1”-ss my -sr LocalMachine -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -in“SelfSignedCA”-is Root -ir LocalMachine -sp“Microsoft RSA SChannel加密提供程序“-sy 12 Client1.cer

因此,只需使用2作为-eku参数: 1.3.6.1.5.5.7.3.2

===============>>#4 票数:0

在任何HTTP流量通过之前,SSL握手必须成功完成。 您收到HTTP响应的事实表明您的SSL设置正常。

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

===============>>#5 票数:0

我遇到了同样的问题(Forbidden 403),我的客户端试图使用MutualAuthentication连接到服务器。 确实,SSL层不是问题,同时服务器没有得到请求,因为它被传输层阻止了。 但是我在2012年的服务器面临着这个问题 - 因为2008年的工作会很好。 通过服务配置启用serviceSecurityAudit

<serviceSecurityAudit auditLogLocation="Application"
            suppressAuditFailure="false" 
            serviceAuthorizationAuditLevel="SuccessOrFailure" 
            messageAuthenticationAuditLevel="SuccessOrFailure" />

将Windows事件日志应用程序端的错误/故障显示为消息身份验证和服务授权错误。

对我有用的解决方案是为clientCertificate via引入自定义证书验证器

   <clientCertificate>              <authentication certificateValidationMode="Custom" customCertificateValidatorType="App.Web.Framework.MyX509CertificateValidator, App.Vertical.Send"  />
   </clientCertificate>

这将需要一个在程序集中实现证书验证方法。

如果需要,我也可以提供这些细节。

谢谢--Kirti Kunal Shah

  ask by typhoid translate from so

未解决问题?本站智能推荐:

1回复

Android客户端上的SSL相互身份验证FAIL接受服务器证书,但服务器未获得客户端证书

我正在尝试在Linux服务器和Android APP之间建立一个相互认证的SSL。 到目前为止,我已经能够让应用程序使用服务器证书通过SSL进行通信,但是一旦我将服务器设置为仅接受客户端证书就停止工作。 服务器配置似乎没问题,但我有点卡住了。 我最好的猜测是客户端证书没有正确呈现给服务器,
1回复

相互SSL异常发送警报:java.net.SocketException:管道断开(写入失败)

我有连接到服务器的客户端应用程序,并且身份验证是相互SSL。 我正在尝试设置双向SSL,但由于以下异常而失败。 我正在使用resttemplate进行休息电话。 相互sll的流程客户端问候,然后服务器问候,然后证书验证,然后在服务器密钥交换也成功之后,客户端证书已由服务器发送了CA,
1回复

离子框架/离子本机http:基于ssl客户端的身份验证

我指的是这个问题: https : //forum.ionicframework.com/t/ionic-native-http-ssl-client-based-authentification/129596 有什么想法如何在离子框架内实现基于ssl客户端的身份验证(相互tls)? 即
1回复

Apache tomcat相互认证自签名证书REST服务

我想在Tomcat上部署我的REST服务(战争),希望它使用自签名证书和相互认证来启用HTTPS。 我需要提出一个使用自签名证书的客户端。 我希望客户端和服务器交换其证书。 我需要有关如何完成此操作的建议。
2回复

使用客户端证书的自定义urllib开启工具

我有一个我必须使用的API。 API由HTTPS保护,并使用相互身份验证/客户端证书。 我有一个PEM文件和一个CRT文件。 当我经常连接到服务器时,使用PyOpenSSL我没有问题,这里是代码: 但是,因为这是一个带有客户端证书的HTTPS API,我已经为它实现了一个开启工
1回复

缺少共同证书的WCF请求缺少wsse:安全性

我正在尝试使用wcf通过相互证书进行SOAP调用,但要么一直出错 “请求已中止:无法创建SSL / TLS安全通道。” 要么 “远程服务器返回错误:(500)内部服务器错误,请求中缺少wsse:Security标头” 在SOAP UI中完成的类似请求有效,但是n C#不想传递
1回复

具有RESTful WCF服务的基于证书的相互SSL

我有一个基于证书的双向(双向)SSL WCF RESTful服务,该服务托管在Windows应用程序中。 服务器使用绑定了自签名证书的端口。 该证书位于“我的”商店的“ LocalMachine”中。 客户端证书也在同一“我的”存储中。 客户端证书和服务器证书的名称都与计算机名称相同。
1回复

wcf服务服务器和客户端证书与SSl证书不同时的安全异常

我是WCF的新手,并且很难理解证书的身份验证和加密。 我有一个使用clientcredentialtype =“ Certificate”的WCF服务。 我已经使用makecert工具生成了CA证书,服务器和客户端证书。 该服务托管在IIS中。 当我将SSl用于我的网站时
1回复

WCF客户端绑定以访问https服务。 无法为具有权限的SSL / TLS建立安全通道

我需要创建WCF客户端来连接通过https提供的服务。 负责WCF的当前客户端配置如下所示: 不幸的是我收到了一个错误: 我没有权限修改任何此服务 更新: 出于测试目的,我忽略了Application_Start中的global.asax中的证书,但我仍然得到相同的
2回复

WCF自托管REST服务器(https)不断要求客户端身份验证

我创建了一个自托管的WCF REST服务器(不带IIS)。 启用S​​SL支持后,在Chrome中测试网站时,系统会一直要求我提供客户端证书。 以下是我的app.config,我认为我禁用了客户端身份验证。 我在这里想念什么吗? 照片: Chrome要求提供客户证书 App