Saya sedang mengerjakan proyek yang perlu terhubung ke situs https. Setiap kali saya terhubung, kode saya memunculkan pengecualian karena sertifikat situs tersebut berasal dari situs tidak tepercaya. Apakah ada cara untuk melewati pemeriksaan sertifikat di .net core http?
Saya melihat kode ini dari versi .NET sebelumnya. Saya rasa saya hanya butuh sesuatu seperti ini.
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
c#
ssl
asp.net-core
ssl-certificate
Ramppy Dumppy
sumber
sumber
Jawaban:
ServicePointManager.ServerCertificateValidationCallback tidak didukung di .Net Core.
Situasi saat ini adalah bahwa itu akan menjadi metode ServerCertificateCustomValidationCallback baru untuk 4.1. * Kontrak System.Net.Http mendatang (HttpClient). Tim .NET Core sedang menyelesaikan kontrak 4.1 sekarang. Anda dapat membaca tentang ini di sini di github
Anda dapat mencoba versi pra-rilis System.Net.Http 4.1 dengan menggunakan sumber langsung di sini di CoreFx atau di umpan MYGET: https://dotnet.myget.org/gallery/dotnet-core
Definisi WinHttpHandler.ServerCertificateCustomValidationCallback saat ini di Github
sumber
Memperbarui:
Seperti disebutkan di bawah, tidak semua implementasi mendukung callback ini (yaitu, platform seperti iOS). Dalam kasus ini, seperti yang dikatakan dokumen , Anda dapat menyetel validator secara eksplisit:
Ini juga berfungsi untuk .NET Core 2.2, 3.0 dan 3.1
Jawaban lama , dengan lebih banyak kendali tetapi mungkin melempar
PlatformNotSupportedException
:Anda dapat mengganti pemeriksaan sertifikat SSL pada panggilan HTTP dengan fungsi panggilan balik anonim seperti ini
using (var httpClientHandler = new HttpClientHandler()) { httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; using (var client = new HttpClient(httpClientHandler)) { // Make your request... } }
Selain itu, saya menyarankan untuk menggunakan pola pabrik
HttpClient
karena ini adalah objek bersama yang mungkin tidak segera dibuang dan karena itu koneksi akan tetap terbuka .sumber
HttpClient
properti bernamaDangerousAcceptAnyServerCertificateValidator
yang menyediakan cara untuk membuat ini berfungsi di MacOSX. Info lebih lanjut di sini - github.com/dotnet/corefx/pull/19908factory pattern
untukHttpClient
?GetHttpClient
Metode mengembalikan konfigurasiHttpClient
dan menggunakannya dalamusing
-block.Saya menyelesaikannya dengan ini:
Startup.cs
public void ConfigureServices(IServiceCollection services) { services.AddHttpClient("HttpClientWithSSLUntrusted").ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Manual, ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => { return true; } });
YourService.cs
public UserService(IHttpClientFactory clientFactory, IOptions<AppSettings> appSettings) { _appSettings = appSettings.Value; _clientFactory = clientFactory; } var request = new HttpRequestMessage(... var client = _clientFactory.CreateClient("HttpClientWithSSLUntrusted"); HttpResponseMessage response = await client.SendAsync(request);
sumber
Datang ke sini mencari jawaban untuk masalah yang sama, tetapi saya menggunakan WCF untuk NET Core. Jika Anda berada di perahu yang sama, gunakan:
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication() { CertificateValidationMode = X509CertificateValidationMode.None, RevocationMode = X509RevocationMode.NoCheck };
sumber
Di .NetCore, Anda dapat menambahkan potongan kode berikut pada metode konfigurasi layanan, saya menambahkan tanda centang untuk memastikan hanya bahwa kami melewatkan sertifikat SSL di lingkungan pengembangan saja
services.AddHttpClient("HttpClientName", client => { // code to configure headers etc.. }).ConfigurePrimaryHttpMessageHandler(() => { var handler = new HttpClientHandler(); if (hostingEnvironment.IsDevelopment()) { handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; } return handler; });
sumber
Saya menghadapi masalah yang sama ketika bekerja dengan sertifikat yang ditandatangani sendiri dan autentikasi sertifikat klien pada wadah .NET Core 2.2 dan Docker Linux. Semuanya bekerja dengan baik di mesin Windows dev saya, tetapi di Docker saya mendapat kesalahan seperti itu:
Untungnya, sertifikat dibuat menggunakan rantai. Tentu saja, Anda selalu dapat mengabaikan solusi ini dan menggunakan solusi di atas.
Jadi inilah solusi saya:
Saya menyimpan sertifikat menggunakan Chrome di komputer saya dalam format P7B .
Ubah sertifikat ke format PEM menggunakan perintah ini:
openssl pkcs7 -inform DER -outform PEM -in <cert>.p7b -print_certs > ca_bundle.crt
Buka file ca_bundle.crt dan hapus semua rekaman Subjek, biarkan file bersih. Contoh di bawah ini:
# 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
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 certs must be installed client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication { CertificateValidationMode = X509CertificateValidationMode.ChainTrust, TrustedStoreLocation = StoreLocation.LocalMachine, RevocationMode = X509RevocationMode.NoCheck };
Metode GetClientCertificate:
private static X509Certificate2 GetClientCertificate(string clientCertName, string password) { //Create X509Certificate2 object from .pfx file 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); }
sumber
Pertama, JANGAN GUNAKAN DALAM PRODUKSI
Jika Anda menggunakan middleware AddHttpClient, ini akan berguna. Saya pikir itu dibutuhkan untuk tujuan pengembangan, bukan produksi. Sampai Anda membuat sertifikat yang valid, Anda dapat menggunakan Func ini.
Func<HttpMessageHandler> configureHandler = () => { var bypassCertValidation = Configuration.GetValue<bool>("BypassRemoteCertificateValidation"); var handler = new HttpClientHandler(); //!DO NOT DO IT IN PRODUCTION!! GO AND CREATE VALID CERTIFICATE! if (bypassCertValidation) { handler.ServerCertificateCustomValidationCallback = (httpRequestMessage, x509Certificate2, x509Chain, sslPolicyErrors) => { return true; }; } return handler; };
dan menerapkannya seperti
services.AddHttpClient<IMyClient, MyClient>(x => { x.BaseAddress = new Uri("https://localhost:5005"); }) .ConfigurePrimaryHttpMessageHandler(configureHandler);
sumber
Mengizinkan semua sertifikat sangat efektif, tetapi juga bisa berbahaya. Jika Anda hanya ingin mengizinkan sertifikat yang valid ditambah beberapa sertifikat tertentu, hal itu dapat dilakukan seperti ini.
using (var httpClientHandler = new HttpClientHandler()) { httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => { if (sslPolicyErrors == SslPolicyErrors.None) { return true; //Is valid } if (cert.GetCertHashString() == "99E92D8447AEF30483B1D7527812C9B7B3A915A7") { return true; } return false; }; using (var httpClient = new HttpClient(httpClientHandler)) { var httpResponse = httpClient.GetAsync("https://example.com").Result; } }
Sumber asli:
https://stackoverflow.com/a/44140506/3850405
sumber