Hi Everyone,
SSL双向认证内容,更加安全的连接;
1、这里将证书安装到“证书 - 当前用户” --> “个人” --> “证书”中;(不会操作的小伙伴百度搜一下吧,我后期维护后再放自己的链接)
原因是:如果安装到本地计算机了,对于当前用户来说无法越级查找敏感信息。在代码中断点调试后可以确认 --> 证书可以获取,但是获取不到证书中的PrivateKey的,会报异常;
2、MMC中找到客户端证书并双击 / “详细信息” -> 获取指纹:
代码片段如下(注意使用Using,可以释放资源)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using log4net;
namespace Helper
{
public class ServiceHelper
{
private static readonly ILog logger = LogManager.GetLogger("ServiceHelper");
//private readonly string _clientCertificateThumbprint = AppSettingHelper.Read("ServiceClientCertificateThumbprint");
private readonly string _clientCertificateThumbprint = "上面图片获取的客户端证书指纹";//Client Thumbprint.
/// <summary>
/// 请求Https并携带客户端证书
/// </summary>
/// <param name="content">Request Body</param>
/// <param name="url">Target URL</param>
/// <param name="headers">Request Headers</param>
/// <param name="method">Post、Get.....</param>
/// <returns></returns>
public async Task<string> RequestServiceAPI(string content, string url, Dictionary<string, string> headers, string method = "Post")
{
try
{
string result = string.Empty;
#region 方式1:通过mmc安装Client Certificate方式
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls |
(SecurityProtocolType)768 | (SecurityProtocolType)3072 |
(SecurityProtocolType)0x300 | (SecurityProtocolType)0xC00;
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; //获取或设置用于验证服务器证书的回调
#if !DEBUG
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); //从 "本地计算机" 安装的Client Certificate中进行查找;//不能使用CurrentUser
#else
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);//从 "计算机当前用户" 安装的Client Certificate中进行查找;也可以使用LocalMachine
#endif
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2 clientCer ;
try
{
//do not use "store.Certificates.Find()" --> Performance
//Case must be omitted;
//Find By certificate thumbprint.
clientCer = store.Certificates.Cast<X509Certificate2>().FirstOrDefault(c => c.Thumbprint.Equals(_clientCertificateThumbprint, StringComparison.OrdinalIgnoreCase));
if (clientCer == null)
{
logger.Info($"Class : {nameof(ServiceHelper)} Method : {nameof(RequestServiceAPI)}; Error : Client certificate with \"{_clientCertificateThumbprint}\" thumbprint not found.");
return null;
}
}
catch
{
logger.Info($"Class : {nameof(ServiceHelper)} Method : {nameof(RequestServiceAPI)}; Error : Client certificate with \"{_clientCertificateThumbprint}\" thumbprint not found.");
return null;
}
finally
{
store.Close();
}
#endregion
#region 方式2:通过路径获取Client Certificate方式;
//try
//{
//string certificatePath = @"....\ClientCertificateFile.pfx";//使用相对路径或者绝对路径,
//string certPassword = "******"; //客户端证书对应的明文密码;
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3|SecurityProtocolType.Tls| (SecurityProtocolType)768|(SecurityProtocolType)3072|(SecurityProtocolType)0x300|(SecurityProtocolType)0xC00;//根据当前framework版本中的枚举进行设置;
//ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;//获取或设置用于验证服务器证书的回调,根据实际情况true或false;
clientCer对象就是请求时携带上去的客户端证书
//X509Certificate2 clientCer = new X509Certificate2(certificatePath, certPassword, X509KeyStorageFlags.MachineKeySet|X509KeyStorageFlags.PersistKeySet|X509KeyStorageFlags.Exportable);
//catch (Exception ex)
//{
//logger.Error($"Get Client certificate Error : {ex}.");
//return null;
//}
#endregion
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(content);
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.ClientCertificates.Add(clientCer);
request.ContentType = "application/json";
request.Method = method;
request.ContentLength = bytes.Length;
if (headers != null && headers.Count > 0)
{
foreach (var item in headers)
{
request.Headers.Add(item.Key, item.Value);
}
}
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
}
using (HttpWebResponse response = (HttpWebResponse) await request.GetResponseAsync())
{
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.UTF8))
{
result = reader.ReadToEnd().Trim();
request.Abort();
}
}
}
}
return result;
}
catch (Exception ex)
{
logger.Info($"Class : {nameof(ServiceHelper)} Method : {nameof(RequestServiceAPI)} happen exception. error: {ex.Message}");
return null;
}
}
}
}
超详细的Asp.net使用SSL双向认证,一篇就够了:
https://blog.csdn.net/qq_39797713/article/details/126130544