简体   繁体   English

WCF wsHttpBinding客户端证书身份验证,不使用客户端中的存储

[英]WCF wsHttpBinding Client Certificate Authentication without using store in client

I have a WCF service registered as such using wsHttpBinding it is hosted in IIS with HTTPS binding to a valid and active certificate: 我有一个使用wsHttpBinding进行注册的WCF服务,它通过IIS托管在IIS中,并通过HTTPS绑定到有效的活动证书:

<?xml version="1.0"?>
<configuration>
  <system.webServer>
    <security>
      <access sslFlags="Ssl, SslNegotiateCert, SslRequireCert"/>
      <authorization>
        <add users="*" accessType="Allow" />
      </authorization>
    </security>
  </system.webServer>
  <system.web>
    <authorization>
      <allow users="*" />
    </authorization>
  </system.web>
  <system.serviceModel>
    <protocolMapping>
      <add scheme="https" binding="wsHttpBinding" />
    </protocolMapping>
    <bindings>
      <wsHttpBinding>
        <binding name="MyNameSpace.WebService_TransportSecurity">
          <security mode="Transport">
            <transport clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyNameSpace.WebService_Behaviour">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="MyNameSpace.WebService" behaviorConfiguration="MyNameSpace.WebService_Behaviour">
        <endpoint address=""
                  binding="wsHttpBinding"
                  bindingConfiguration="MyNameSpace.WebService_TransportSecurity"
                  contract="MyNameSpace.IMyServiceContract">
        </endpoint>

        <endpoint address="mex"
                             binding="mexHttpsBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

I'm using .NET 4 so as far as I can tell this is the only binding that works with SSL and client certificate authentication. 据我所知,我正在使用.NET 4,这是唯一适用于SSL和客户端证书身份验证的绑定。

I've generated the standard proxy using svcutil and trying to set the certificate (self signed that is also in the server) using it's base64 representation: 我已经使用svcutil生成了标准代理,并尝试使用base64表示法来设置证书(也在服务器中进行自签名):

X509Certificate2 certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(System.Convert.FromBase64String("thebase64ofthecertificate"));
if (certificate == null)
{
    return null;
}
IMyServiceContractClient client = new IMyServiceContractClient(new System.ServiceModel.WSHttpBinding
{
    Security = new System.ServiceModel.WSHttpSecurity
    {
        Mode = System.ServiceModel.SecurityMode.Transport,
        Transport = new System.ServiceModel.HttpTransportSecurity
        {

            ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Certificate
        }
    }
},
new System.ServiceModel.EndpointAddress(new System.Uri("https://myserviceendpoint/webservice.svc")));
client.ClientCredentials.ClientCertificate.Certificate = certificate;

But it does not work if I don't also have the certificate in my local computer store, I get this error: 但是,如果我在本地计算机商店中也没有证书,那将无法正常工作,我会收到以下错误消息:

在此处输入图片说明

I'm not an expert in security, ssl or certificates, but is this feasible? 我不是安全性,ssl或证书方面的专家,但这可行吗?

All I'm trying to achieve is to ensure that my service is only called by this code, and thought that using self-signed client certificates that are validated in the server would do, but if they need to be in the store it adds unnecessary complexity to the whole thing! 我要实现的所有目的是确保仅通过此代码调用我的服务,并认为使用在服务器中经过验证的自签名客户端证书可以这样做,但是如果它们需要存储在商店中,则会增加不必要的麻烦整个事情的复杂性!


UPDATE 1: 更新1:

As suggested by Yacoub Massad exporting certificate's Base64 with X509ContentType.Pkcs12 yields exception: 根据Yacoub Massad的建议,导出带有X509ContentType.Pkcs12的证书的Base64会产生异常:

An unhandled exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll

Additional information: Key not valid for use in specified state.

I'm loading the certificate from store with: 我正在使用以下方法从商店加载证书:

    X509Certificate2 certificate = null;
    X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
    try
    {
        store.Open(OpenFlags.ReadWrite);
        var r = store.Certificates.Find(X509FindType.FindBySubjectName, "LicensingCert", false);
        if (r.Count > 0)
            certificate = r[0];
    }
    catch
    {
        certificate = null;
    }
    finally
    {
        if (store != null)
            store.Close();
    }

    if (certificate == null)
    {
        return null;
    }
    File.WriteAllText(@"C:\tmp\certs\ExportLicensingCert.txt", Convert.ToBase64String(certificate.Export(X509ContentType.Pkcs12)));

UPDATE 2: 更新2:

Made sure the certificate had been imported with Mark as exportable and it did the trick, I must have skipped that the first time I imported the certificate. 确保使用Mark将其导入为可导出证书,并且做到了这一招,我一定是在第一次导入证书时就跳过了。 Now testing the compiled code on another computer has stopped doing the error. 现在在另一台计算机上测试编译的代码已停止执行此错误。 Thank you so much Yacoub Massad for pointing me in the right direction :) 非常感谢Yacoub Massad指出正确的方向:)

For certificate authentication to work, the client needs the private key to prove its identity to the server. 为了使证书身份验证起作用,客户端需要私钥向服务器证明其身份。 The certificate alone will not work. 单独的证书将不起作用。

Make sure that the X509Certificate2 that you setup the WCF client to use has a corresponding private key. 确保设置WCF客户端以使用的X509Certificate2具有相应的私钥。

You need a PFX file that contains the certificate and the private key and you need to import them into a X509Certificate2 object via the Import method. 您需要一个包含证书和私钥的PFX文件,并且需要通过Import方法将它们导入X509Certificate2对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM