简体   繁体   English

使用客户端证书身份验证连接到Web服务

[英]Connecting to a Web Service using Client Certificate authentication

I've been give a .p12 file to connect to a web service over SSL using client certificate authentication. 我一直在使用客户端证书身份验证通过SSL连接到Web服务的.p12文件。 I have this successfully working in PHP, using cURL. 我使用cURL成功地在PHP中工作。 These are the options I'm using when perform the request: 这些是我在执行请求时使用的选项:

$headers = array(
    'Method: POST',
    'Connection: Keep-Alive',
    'User-Agent: PHP-SOAP-CURL',
    'Content-Type: text/xml; charset=utf-8',
    'SOAPAction: "'.$action.'"',
);

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $location);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_SSLCERT, $this->clientcert);
curl_setopt($ch, CURLOPT_SSLKEYTYPE, $this->clientcerttype);
curl_setopt($ch, CURLOPT_SSLKEY, $this->keyfile);
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $this->keypassword);
curl_setopt($ch, CURLOPT_SSLVERSION, 3);

$response = curl_exec($ch);

I'm now trying to do the same task using C# and .NET, but I keep getting the error "Could not establish secure channel for SSL/TLS with authority ':'.". 我现在正在尝试使用C#和.NET执行相同的任务,但我不断收到错误“无法建立具有权限的SSL / TLS的安全通道:'。”。

I don't seem to have an issue with locating the key, and there don't appear to be any trust issues. 我似乎没有找到密钥的问题,似乎没有任何信任问题。 Still, something isn't right, somewhere along the line. 然而,某些事情是不对的,在某个地方。

I've made a test program, just so I can test that a basic call will work. 我做了一个测试程序,这样我就可以测试一个基本的调用是否有效。

public void StartviaWSHttp()
{
    var binding = new WSHttpBinding();
    binding.Security.Mode = SecurityMode.Transport;
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
    binding.Security.Message.NegotiateServiceCredential = false;
    binding.Security.Message.ClientCredentialType = MessageCredentialType.None;

    var baseAddress = new Uri("https://<host>:<port>/LineEndpoint1");
    var endpointAddress = new EndpointAddress(baseAddress);

    var client = new LinePortTypeClient(binding, endpointAddress);

    client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySerialNumber, "00d48a233bf4b77523");

    Debug.Assert(client.ClientCredentials.ClientCertificate.Certificate.SerialNumber.ToLower() == "00d48a233bf4b77523");

    var header = new ctSoapHeaderMsg();
    var response = new object();
    client.Open();
    var responseCode = client.PerformFunction(ref header, "0893411111", out response);
    client.Close();

    Console.WriteLine("Response Code :" + responseCode);
    Console.WriteLine("Response :" + response);
}

When I view the certificate in the Personal/Certificates for Current User, it does not report any issues, with regards to trust. 当我在当前用户的个人/证书中查看证书时,它不会报告任何与信任有关的问题。 In the certificate information, it says that the certificate in intended for the following purposes: All issuance policies and all application policies. 在证书信息中,它表示该证书用于以下目的:所有颁发策略和所有应用程序策略。 The Certification Path only has one entry, and the Certificate status reports that "This certificate is OK." 证书路径只有一个条目,证书状态报告“此证书正常”。

I'm at a loss for what the issue is. 我对这个问题感到茫然。 Perhaps there is a trust issue, since I have PEER and HOST verification off for the PHP call. 也许存在信任问题,因为我已经关闭了PHP调用的PEER和HOST验证。 I'm not sure if that is an option for C#. 我不确定这是否是C#的选项。


Update: (9 August 2013) I set up some verbose tracing for System.Net and System.Net.Socket. 更新:(2013年8月9日)我为System.Net和System.Net.Socket设置了一些详细的跟踪。 This is the start of the output. 这是输出的开始。

System.Net Verbose: 0 : [16124] WebRequest::Create(https://dsl-wholesale-testing.iinet.net.au:50500/LineEndpoint1)
System.Net Verbose: 0 : [16124] HttpWebRequest#58508234::HttpWebRequest(https://dsl-wholesale-testing.iinet.net.au:50500/LineEndpoint1#128335743)
System.Net Information: 0 : [16124] Current OS installation type is 'Client'.
System.Net Information: 0 : [16124] RAS supported: True
System.Net Verbose: 0 : [16124] Exiting HttpWebRequest#58508234::HttpWebRequest() 
System.Net Verbose: 0 : [16124] Exiting WebRequest::Create()    -> HttpWebRequest#58508234
System.Net Verbose: 0 : [16124] ServicePoint#36898364::ServicePoint(dsl-wholesale-testing.iinet.net.au:50500)
System.Net Information: 0 : [16124] Associating HttpWebRequest#58508234 with ServicePoint#36898364
System.Net Verbose: 0 : [16124] HttpWebRequest#58508234::GetRequestStream()
System.Net Information: 0 : [16124] Associating Connection#47995487 with HttpWebRequest#58508234
System.Net.Sockets Verbose: 0 : [16124] Socket#31002555::Socket(AddressFamily#2)
System.Net.Sockets Verbose: 0 : [16124] Exiting Socket#31002555::Socket() 
System.Net.Sockets Verbose: 0 : [16124] Socket#6243847::Socket(AddressFamily#23)
System.Net.Sockets Verbose: 0 : [16124] Exiting Socket#6243847::Socket() 
System.Net.Sockets Verbose: 0 : [16124] DNS::TryInternalResolve(dsl-wholesale-testing.iinet.net.au)
System.Net.Sockets Verbose: 0 : [16124] Socket#31002555::Connect(203.173.51.130:50500#-2110560113)
System.Net.Sockets Information: 0 : [16124] Socket#31002555 - Created connection from 192.168.190.202:55397 to 203.173.51.130:50500.
System.Net.Sockets Verbose: 0 : [16124] Exiting Socket#31002555::Connect() 
System.Net.Sockets Verbose: 0 : [16124] Socket#6243847::Close()
System.Net.Sockets Verbose: 0 : [16124] Socket#6243847::Dispose()
System.Net.Sockets Verbose: 0 : [16124] Exiting Socket#6243847::Close() 
System.Net Information: 0 : [16124] Connection#47995487 - Created connection from 192.168.190.202:55397 to 203.173.51.130:50500.
System.Net Information: 0 : [16124] TlsStream#29695768::.ctor(host=dsl-wholesale-testing.iinet.net.au, #certs=0)
System.Net Information: 0 : [16124] Associating HttpWebRequest#58508234 with ConnectStream#25001628
System.Net Verbose: 0 : [16124] Exiting HttpWebRequest#58508234::GetRequestStream()     -> ConnectStream#25001628
System.Net Verbose: 0 : [16124] ConnectStream#25001628::Write()
System.Net Verbose: 0 : [16124] Data from ConnectStream#25001628::Write
System.Net Verbose: 0 : [16124] (printing 1024 out of 1206)
System.Net Verbose: 0 : [16124] 00000000 : 3C 73 3A 45 6E 76 65 6C-6F 70 65 20 78 6D 6C 6E : <s:Envelope xmln

The line System.Net Information: 0 : [16124] TlsStream#29695768::.ctor(host=dsl-wholesale-testing.iinet.net.au, #certs=0) suggests that no certificates have been picked up for use, even though I've attached the certificate to the client.ClientCredentials.ClientCertificate, but I'm not sure why this is happening or how to make it stick. System.Net Information: 0 : [16124] TlsStream#29695768::.ctor(host=dsl-wholesale-testing.iinet.net.au, #certs=0)System.Net Information: 0 : [16124] TlsStream#29695768::.ctor(host=dsl-wholesale-testing.iinet.net.au, #certs=0)表明没有证书被提取使用,即使我已将证书附加到client.ClientCredentials.ClientCertificate,但我不确定为什么会发生这种情况或如何使它坚持下去。 Do any properties of the certificate have to match the hostname that I'm connecting to? 证书的任何属性是否必须与我要连接的主机名相匹配?

It appears that the server did not understand TLS. 看来服务器不了解TLS。

I had to specify SSLv3, via 我不得不指定SSLv3,via

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3;

As @ajeh mentioned in the comments "transport clientCredentialType=..." worked for me! 正如@ajeh在评论中提到的“transport clientCredentialType = ...”为我工作!

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

Also, you need to make sure that your IIS application pool user has permission to read private key of your certificate. 此外,您需要确保您的IIS应用程序池用户有权读取证书的私钥。

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

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