Próbuję znaleźć sposób na zignorowanie sprawdzania certyfikatu, gdy żądam zasobu HTTPS, do tej pory znalazłem pomocny artykuł w Internecie.
Ale wciąż mam problem. Proszę przejrzeć mój kod. Po prostu nie rozumiem, co oznacza kod ServicePointManager.ServerCertificateValidationCallback
.
Kiedy zostanie wywołana ta metoda delegata? I jeszcze jedno pytanie, w którym miejscu mam napisać ten kod? Przed ServicePointManager.ServerCertificateValidationCallback
wykonaniem czy przed Stream stream = request.GetRequestStream()
?
public HttpWebRequest GetRequest()
{
CookieContainer cookieContainer = new CookieContainer();
// Create a request to the server
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_remoteUrl);
#region Set request parameters
request.Method = _context.Request.HttpMethod;
request.UserAgent = _context.Request.UserAgent;
request.KeepAlive = true;
request.CookieContainer = cookieContainer;
request.PreAuthenticate = true;
request.AllowAutoRedirect = false;
#endregion
// For POST, write the post data extracted from the incoming request
if (request.Method == "POST")
{
Stream clientStream = _context.Request.InputStream;
request.ContentType = _context.Request.ContentType;
request.ContentLength = clientStream.Length;
ServicePointManager.ServerCertificateValidationCallback = delegate(
Object obj, X509Certificate certificate, X509Chain chain,
SslPolicyErrors errors)
{
return (true);
};
Stream stream = request.GetRequestStream();
....
}
....
return request;
}
}
c#
ssl
httpwebrequest
certificate
Joe.wang
źródło
źródło
Odpowiedzi:
Ponieważ istnieje tylko jeden globalny ServicePointManager , ustawienie ServicePointManager.ServerCertificateValidationCallback spowoduje, że wszystkie kolejne żądania odziedziczą tę zasadę. Ponieważ jest to globalne „ustawienie”, preferowane byłoby ustawienie go w metodzie Application_Start w Global.asax .
Ustawienie wywołania zwrotnego przesłania domyślne zachowanie i możesz samodzielnie utworzyć niestandardową procedurę sprawdzania poprawności.
źródło
HttpWebRequest
. Jeśli używasz innych środków, musisz zajrzeć do dokumentacji, jak to zrobić.Dla wszystkich zainteresowanych zastosowaniem tego rozwiązania na żądanie, jest to opcja i używa wyrażenia Lambda. To samo wyrażenie lambda można zastosować również do filtru globalnego, o którym wspomina blak3r. Wydaje się, że ta metoda wymaga platformy .NET 4.5.
String url = "https://www.stackoverflow.com"; HttpWebRequest request = HttpWebRequest.CreateHttp(url); request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
W .NET 4.0 wyrażenie Lambda można zastosować do filtru globalnego jako takiego
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
źródło
true
jest czymś, co możesz zrobić podczas eksperymentowania podczas programowania, jednak jest to niebezpieczne. Powinien być warunkowy.(HttpWebRequest)WebRequest.Create(url)
jest całkowicie poprawne, ale na moim pudełkuHttpWebRequest.Create(url)
nadal istnieje w projekcie przeznaczonym dla .Net 4.6.2. Wybór szefa kuchni, ale w tym momencieHttpClient
jest prawdopodobnie lepszym API do użycia.To zadziałało dla mnie:
System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; // **** Always accept };
Fragment stąd: http://www.west-wind.com/weblog/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors
źródło
Istnieje również krótkie rozwiązanie delegata:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
źródło
true
jest niepewny.Nawiasem mówiąc, jest to najmniej rozwlekły sposób na wyłączenie całej weryfikacji certyfikatu w danej aplikacji, o którym wiem:
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
źródło
Wspomniano, że przed .NET 4.5 właściwość na żądanie dostępu do niej
ServicePointManager
nie była dostępna.Oto kod .NET 4.0, który zapewni dostęp do programu
ServicePoint
na żądanie. Nie daje dostępu do wywołania zwrotnego na żądanie, ale powinien pozwolić ci dowiedzieć się więcej szczegółów o problemie. Po prostu uzyskaj dostęp doscvPoint.Certificate
(lubClientCertificate
jeśli wolisz) właściwości.WebRequest request = WebRequest.Create(uri); // oddity: these two .Address values are not necessarily the same! // The service point appears to be related to the .Host, not the Uri itself. // So, check the .Host vlaues before fussing in the debugger. // ServicePoint svcPoint = ServicePointManager.FindServicePoint(uri); if (null != svcPoint) { if (!request.RequestUri.Host.Equals(svcPoint.Address.Host, StringComparison.OrdinalIgnoreCase)) { Debug.WriteLine(".Address == " + request.RequestUri.ToString()); Debug.WriteLine(".ServicePoint.Address == " + svcPoint.Address.ToString()); } Debug.WriteLine(".IssuerName == " + svcPoint.Certificate.GetIssuerName()); }
źródło
ignore
im, a nie im ufać.ServicePoint
Nie zawsze mogę ufać wszystkim certyfikatom SSL, ani ignorować wszystkich certyfikatów , ponieważ nieServerCertificateValidationCallback
delegowałem w ServicePointZamiast dodawać wywołanie zwrotne do ServicePointManager, które globalnie przesłoni weryfikację certyfikatu, możesz ustawić wywołanie zwrotne w lokalnym wystąpieniu HttpClient. To podejście powinno wpływać tylko na wywołania wykonane przy użyciu tego wystąpienia HttpClient.
Oto przykładowy kod pokazujący, jak ignorowanie błędów weryfikacji certyfikatu dla określonych serwerów może zostać zaimplementowane w kontrolerze interfejsu API sieci Web.
using System.Net.Http; using System.Net.Security; using System.Security.Cryptography.X509Certificates; public class MyController : ApiController { // use this HttpClient instance when making calls that need cert errors suppressed private static readonly HttpClient httpClient; static MyController() { // create a separate handler for use in this controller var handler = new HttpClientHandler(); // add a custom certificate validation callback to the handler handler.ServerCertificateCustomValidationCallback = ((sender, cert, chain, errors) => ValidateCert(sender, cert, chain, errors)); // create an HttpClient that will use the handler httpClient = new HttpClient(handler); } protected static ValidateCert(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors) { // set a list of servers for which cert validation errors will be ignored var overrideCerts = new string[] { "myproblemserver", "someotherserver", "localhost" }; // if the server is in the override list, then ignore any validation errors var serverName = cert.Subject.ToLower(); if (overrideCerts.Any(overrideName => serverName.Contains(overrideName))) return true; // otherwise use the standard validation results return errors == SslPolicyErrors.None; } }
źródło
Dla .net core
using (var handler = new HttpClientHandler()) { // allow the bad certificate handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => true; using (var httpClient = new HttpClient(handler)) { await httpClient.PostAsync("the_url", null); } }
źródło
Na podstawie odpowiedzi Adama i komentarza Roba użyłem tego:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => certificate.Issuer == "CN=localhost";
który nieco filtruje „ignorowanie”. W razie potrzeby można oczywiście dodać innych emitentów. Zostało to przetestowane w .NET 2.0, ponieważ potrzebujemy obsługiwać starszy kod.
źródło
CA5386: Narzędzia do analizy luk ostrzegają o tych kodach.
Prawidłowy kod:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return (sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != SslPolicyErrors.RemoteCertificateNotAvailable; };
źródło
Wyraźnie wyrażone ...
ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(CertCheck); private static bool CertCheck(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error) { return true; }
źródło
Wersja Unity C # tego rozwiązania:
void Awake() { System.Net.ServicePointManager.ServerCertificateValidationCallback += ValidateCertification; } void OnDestroy() { ServerCertificateValidationCallback = null; } public static bool ValidateCertification(object sender, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; }
źródło
Dodając do odpowiedzi Sani i blak3r, dodałem do kodu startowego mojej aplikacji, ale w VB:
'** Overriding the certificate validation check. Net.ServicePointManager.ServerCertificateValidationCallback = Function(sender, certificate, chain, sslPolicyErrors) True
Wydaje się, że to załatwia sprawę.
źródło
Wskazówka: możesz również użyć tej metody do śledzenia certyfikatów, które wkrótce wygasną. Może to uratować twój bekon, jeśli odkryjesz certyfikat, który wkrótce wygaśnie i możesz go naprawić na czas. Dobre również dla firm zewnętrznych - dla nas to DHL / FedEx. DHL właśnie pozwolił wygasnąć certyfikatowi, co szkodzi nam 3 dni przed Świętem Dziękczynienia. Na szczęście jestem w pobliżu, aby to naprawić ... tym razem!
private static DateTime? _nextCertWarning; private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) { if (error == SslPolicyErrors.None) { var cert2 = cert as X509Certificate2; if (cert2 != null) { // If cert expires within 2 days send an alert every 2 hours if (cert2.NotAfter.AddDays(-2) < DateTime.Now) { if (_nextCertWarning == null || _nextCertWarning < DateTime.Now) { _nextCertWarning = DateTime.Now.AddHours(2); ProwlUtil.StepReached("CERT EXPIRING WITHIN 2 DAYS " + cert, cert.GetCertHashString()); // this is my own function } } } return true; } else { switch (cert.GetCertHashString()) { // Machine certs - SELF SIGNED case "066CF9CAD814DE2097D367F22D3A7E398B87C4D6": return true; default: ProwlUtil.StepReached("UNTRUSTED CERT " + cert, cert.GetCertHashString()); return false; } } }
źródło
ProwlUtil.StepReached
?Kilka odpowiedzi powyżej działa. Zależało mi na podejściu, dzięki któremu nie musiałem ciągle wprowadzać zmian w kodzie i nie powodowałoby, że kod byłby niezabezpieczony. Dlatego stworzyłem białą listę. Biała lista może być utrzymywana w dowolnym magazynie danych. Użyłem pliku konfiguracyjnego, ponieważ jest to bardzo mała lista.
Mój kod jest poniżej.
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => { return error == System.Net.Security.SslPolicyErrors.None || certificateWhitelist.Contains(cert.GetCertHashString()); };
źródło