我正在构建一个Web Api(使用ASP.NET Web API),它通过Secure WebSockets连接到我们的客户端公开的端点(wss://client-domain:4747/app/engineData
)。他们以.pem格式(root.pem
和client.pem
)以及私钥(client_key.pem
)向我提供了证书。
为了完成这项工作,我做了以下工作:
1)将client.pem
和client_key.pem
转换为单个.pfx
文件(在此处使用:Convert a CERT/PEM certificate to a PFX certificate)
2)我使用了库System.Net.WebSockets
,并编写了以下代码:
private void InitWebSockesClient()
{
client = new ClientWebSocket();
client.Options.SetRequestHeader(HEADER_KEY, HEADER_VALUE); //Some headers I need
AddCertificatesSecurity();
}
private void AddCertificatesSecurity()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12;
// I KNOW THIS SHOULDNT BE USED ON PROD, had to use it to make it
// work locally.
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
X509Certificate2 x509 = new X509Certificate2();
// this is the pfx I converted from client.pem and client_key
byte[] rawData = ReadFile(certificatesPath + @"\cert.pfx");
x509.Import(rawData, "123456", X509KeyStorageFlags.UserKeySet);
X509Certificate2Collection certificateCollection = new X509Certificate2Collection(x509);
client.Options.ClientCertificates = certificateCollection;
}
当我想要连接时,我打电话:
public async Task<bool> Connect()
{
Uri uriToConnect = new Uri(URL);
await client.ConnectAsync(uriToConnect, CancellationToken.None);
return client.State == WebSocketState.Open;
}
这在本地工作正常。但每当我在Azure(App Service)上部署我的Web Api并向其发出HTTP请求时,它都会抛出:
System.Net.WebSockets.WebSocketException - Unable to connect to the remote server.
内在的例外:
System.Net.WebException - The request was aborted: Could not create SSL/TLS secure channel.
我在AppService实例上启用了WebSockets。
如果我删除总是为证书验证返回true的行,它甚至在本地也不起作用,并且消息说明如下:
The remote certificate is invalid according to the validation procedure.
所以肯定我的证书有问题,这三个.pem文件现在正在一个类似的[![在此处输入图像描述] [1]] [1]应用程序中使用node.js并正常工作,WSS连接正确建立。我真的不知道每个人的用法是什么,所以我有点迷失在这里。
这些是我想要连接的域的密码套件:https://i.stack.imgur.com/ZFbo3.png
答案 0 :(得分:1)
受汤姆评论的启发,我终于通过在Azure App Service中将证书添加到Web App而不是尝试从文件系统中使用它来使其工作。首先,我将.pfx文件上载到Azure的SSL证书部分。然后,在应用程序设置中,我添加了一个名为WEBSITE_LOAD_CERTIFICATES的设置,其中包含我想要的证书(.pfx)的指纹。
之后,我修改了我的代码来做这样的工作:
private void InitWebSockesClient()
{
client = new ClientWebSocket();
client.Options.SetRequestHeader(HEADER_KEY, HEADER_VALUE); //Some headers I need
AddCertificateToWebSocketsClient();
}
private void AddCertificateToWebSocketsClient()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12;
// this should really validate the cert
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
// reading cert from store
X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection =
certStore.Certificates.Find(X509FindType.FindByThumbprint,
CERTIFICATES_THUMBPRINT,
false);
if (certCollection.Count > 0)
{
client.Options.ClientCertificates = certCollection;
}
else
{
// handle error
}
certStore.Close();
}
CERTIFICATES_THUMBPRINT是一个字符串(证书的指纹图,即您在Azure上看到的那个)。
如果您想让它在本地运行,您只需要在您的计算机上安装证书,否则它很难在商店中找到它。
Azure文档中对所有这些内容的引用:https://docs.microsoft.com/en-us/azure/app-service/app-service-web-ssl-cert-load。