Tôi đã gặp phải vấn đề tương tự khi làm việc với chứng chỉ tự ký và xác thực chứng chỉ ứng dụng khách trên các vùng chứa .NET Core 2.2 và Docker Linux. Mọi thứ hoạt động tốt trên máy Windows dev của tôi, nhưng trong Docker, tôi gặp lỗi như vậy:
System.Security.Authentication.AuthenticationException: Chứng chỉ từ xa không hợp lệ theo quy trình xác thực
May mắn thay, chứng chỉ được tạo bằng chuỗi. Tất nhiên, bạn luôn có thể bỏ qua giải pháp này và sử dụng các giải pháp trên.
Vì vậy, đây là giải pháp của tôi:
Tôi đã lưu chứng chỉ bằng Chrome trên máy tính của mình ở định dạng P7B .
Chuyển đổi chứng chỉ sang định dạng PEM bằng lệnh này:
openssl pkcs7 -inform DER -outform PEM -in <cert>.p7b -print_certs > ca_bundle.crt
Mở tệp ca_bundle.crt và xóa tất cả các bản ghi Chủ đề, để lại một tệp sạch. Ví dụ bên dưới:
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
- Đặt những dòng này vào Dockerfile (trong các bước cuối cùng):
# Update system and install curl and ca-certificates
RUN apt-get update && apt-get install -y curl && apt-get install -y ca-certificates
# Copy your bundle file to the system trusted storage
COPY ./ca_bundle.crt /usr/local/share/ca-certificates/ca_bundle.crt
# During docker build, after this line you will get such output: 1 added, 0 removed; done.
RUN update-ca-certificates
- Trong ứng dụng:
var address = new EndpointAddress("https://serviceUrl");
var binding = new BasicHttpsBinding
{
CloseTimeout = new TimeSpan(0, 1, 0),
OpenTimeout = new TimeSpan(0, 1, 0),
ReceiveTimeout = new TimeSpan(0, 1, 0),
SendTimeout = new TimeSpan(0, 1, 0),
MaxBufferPoolSize = 524288,
MaxBufferSize = 65536,
MaxReceivedMessageSize = 65536,
TextEncoding = Encoding.UTF8,
TransferMode = TransferMode.Buffered,
UseDefaultWebProxy = true,
AllowCookies = false,
BypassProxyOnLocal = false,
ReaderQuotas = XmlDictionaryReaderQuotas.Max,
Security =
{
Mode = BasicHttpsSecurityMode.Transport,
Transport = new HttpTransportSecurity
{
ClientCredentialType = HttpClientCredentialType.Certificate,
ProxyCredentialType = HttpProxyCredentialType.None
}
}
};
var client = new MyWSClient(binding, address);
client.ClientCredentials.ClientCertificate.Certificate = GetClientCertificate("clientCert.pfx", "passwordForClientCert");
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication
{
CertificateValidationMode = X509CertificateValidationMode.ChainTrust,
TrustedStoreLocation = StoreLocation.LocalMachine,
RevocationMode = X509RevocationMode.NoCheck
};
Phương thức GetClientCertificate:
private static X509Certificate2 GetClientCertificate(string clientCertName, string password)
{
byte[] rawData = null;
using (var f = new FileStream(Path.Combine(AppContext.BaseDirectory, clientCertName), FileMode.Open, FileAccess.Read))
{
var size = (int)f.Length;
var rawData = new byte[size];
f.Read(rawData, 0, size);
f.Close();
}
return new X509Certificate2(rawData, password);
}