使用自创建证书的WCF SecurityTokenValidationException [英] WCF SecurityTokenValidationException using self-created certificate

查看:90
本文介绍了使用自创建证书的WCF SecurityTokenValidationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用自创建证书的WCF客户端连接时遇到问题。

I'm experiencing a problem with WCF client connections using a self-created certificate.

创建的证书如下:

Makecert -r -pe -n "CN=MySslSocketCertificate" -b 01/01/2015 -e 01/01/2025 -sk exchange -ss my

服务器代码:

Public Sub StartWcfServer()
    Dim binding As New NetTcpBinding()

    binding.Security.Mode = SecurityMode.Transport
    binding.Security.Transport.ProtectionLevel = Net.Security.ProtectionLevel.EncryptAndSign
    binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate
    binding.TransferMode = TransferMode.Streamed
    Dim baseAddress As New Uri($"net.tcp://192.168.1.1:1234/WcfServer")

    _serviceHost = New ServiceHost(GetType(WcfServer), baseAddress)
    _serviceHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindByIssuerName, "MySslSocketCertificate")
    _serviceHost.Credentials.ClientCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck
    _serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = ServiceModel.Security.X509CertificateValidationMode.None
    _serviceHost.Credentials.ClientCertificate.Authentication.TrustedStoreLocation = StoreLocation.CurrentUser

    ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate)
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 Or SecurityProtocolType.Tls12

    _serviceHost.AddServiceEndpoint(GetType(IWcfServer), binding, baseAddress)
    _serviceHost.Open()
End Sub

Private Function ValidateServerCertificate(sender As Object, certificate As X509Certificate, chain As X509Chain, sslPolicyErrors As SslPolicyErrors) As Boolean
    Return True
End Function

客户代码:

private void InitialiseWcfClient()
{
    var binding = new NetTcpBinding();
    binding.Security.Mode = SecurityMode.Transport;
    binding.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
    binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
    binding.TransferMode = TransferMode.Streamed;

    var url = $"net.tcp://192.168.1.1:1234/WcfServer";
    var address = new EndpointAddress(url);
    var channelFactory = new ChannelFactory<IWcfServer>(binding, address);

    WcfServer = channelFactory.CreateChannel();
}

// call to server which causes the error
WcfServer.CallMethod();

客户端错误:

System.IdentityModel.Tokens.SecurityTokenValidationException: 'The X.509 certificate CN=MySslSocketCertificate chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

服务器端错误:

System.Security.Authentication.AuthenticationException: 'The remote certificate is invalid according to the validation procedure.'


推荐答案

Bro,无论我们是否在服务器端指定身份验证模式,在对客户端进行身份验证时都应在服务器和客户端之间建立信任关系

即,我们应该在客户端安装服务器证书,并在服务器端安装客户端证书。根据身份验证模式的值,证书的安装位置有所不同,通常应将其安装在本地CA中。此外,考虑到一些访问权限问题,我们最好将证书安装在当前用户之外的本地计算机存储位置。
此外,当我们明确指定安全性为传输时,应在安全性上提供证书。服务器端。

Bro,regardless of whether we specify the Authencation mode on the server-side, we should establish the trust relationship between the server and the client when authenticating the client with a certificate.
Namely, we should install the server certificate on the client-side and install the client certificate on the server side. Based on the authentication mode value, the certificate installation place is difference, commonly we should install it in the Local CA. Besides, considering some access permission issues, we had better install the certificate in Local machine store location other than Current User.
Also, when we explicitly specify the security mode to Transport, we should provide a certificate on the server side.

sh.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "cbc81f77ed01a9784a12483030ccd497f01be71c");

同时,客户端应提供代表身份的证书。

At the same time, the client is supposed to provide a certificate to represent identity.

factory.Credentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "9ee8be61d875bd6e1108c98b590386d0a489a9ca");

我做了一个演示,希望对您有帮助。

服务器。

I have made a demo, ,wish it is helpful to you.
Server.

 class Program
{
    static void Main(string[] args)
    {
        using (ServiceHost sh = new ServiceHost(typeof(MyService)))
        {
            sh.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "cbc81f77ed01a9784a12483030ccd497f01be71c");
            sh.Open();
            Console.WriteLine("serivce is ready....");
            Console.ReadLine();
            sh.Close();
        }
    }
}
[ServiceContract]
public interface IService
{
    [OperationContract]
    string Test();

}
public class MyService : IService
{

    public string Test()
    {
        return DateTime.Now.ToString();
    }
}

App.config(服务器端)

<system.serviceModel>
  <services>
    <service name="VM1.MyService">
      <endpoint address="" binding="netTcpBinding" contract="VM1.IService" bindingConfiguration="mybinding">
      </endpoint>
      <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" ></endpoint>
      <host>
        <baseAddresses>
          <add baseAddress="net.tcp://localhost:5566"/>
        </baseAddresses>
      </host>
    </service>
  </services>
  <bindings>
    <netTcpBinding>
      <binding name="mybinding">
        <security mode="Transport">
          <transport clientCredentialType="Certificate"></transport>
        </security>
      </binding>
    </netTcpBinding>
  </bindings>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <serviceMetadata />
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

客户。

class Program
{
    static void Main(string[] args)
    {

        Uri uri = new Uri("net.tcp://vabqia969vm:5566");
        NetTcpBinding binding = new NetTcpBinding();
        binding.Security.Mode = SecurityMode.Transport;
        binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
        ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri));
        factory.Credentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "9ee8be61d875bd6e1108c98b590386d0a489a9ca");
        IService service = factory.CreateChannel();
        try
        {
            var result = service.Test();
            Console.WriteLine(result);
        }
        catch (Exception)
        {

            throw;
        }


    }

}
[ServiceContract]
public interface IService
{
    [OperationContract]
    string Test();

}

结果。



必须注意的另一件事是,我们应确保客户端证书具有预期的客户端身份验证。


Result.

One more thing must be noted that we should ensure the client certificate have the client authentication Intended purposes.

请随时告诉我是否有需要帮助的地方。

Feel free to let me know if there is anything I can help with.

这篇关于使用自创建证书的WCF SecurityTokenValidationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆