Como faço para usar o WebRequest para acessar um site criptografado SSL usando https?


116

Estou escrevendo um programa que lê o conteúdo de um URL fornecido pelo usuário. Meu problema está no código mais ou menos assim:

Uri uri = new Uri(url);
WebRequest webRequest = WebRequest.Create(uri);
WebResponse webResponse = webRequest.GetResponse();
ReadFrom(webResponse.GetResponseStream());

E isso não funciona se o URL fornecido for um URL "https: //". Alguém pode me ajudar a mudar este código para que funcione com conteúdo criptografado SSL. Obrigado.

Respostas:


175

Você está fazendo isso da maneira correta, mas os usuários podem estar fornecendo urls para sites que possuem certificados SSL inválidos instalados. Você pode ignorar esses problemas de certificado se colocar esta linha antes de fazer a solicitação da web real:

ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);

onde AcceptAllCertificationsé definido como

public bool AcceptAllCertifications(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certification, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
    return true;
}

41
Obrigado por esta resposta! Para evitar algum código inútil, usei-o assim: ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;
Charles Ouellet

4
Obrigado, você me ajudou senhor. F # torna isso muito mais fácil:ServicePointManager.ServerCertificateValidationCallback <- Security.RemoteCertificateValidationCallback (fun _ _ _ _ -> true)
David Grenier

2
@Charles Ouellet Acho que sou ainda mais preguiçoso do que você, (a, b, c, d) => true
Despertar

24
Eu prefiro+= delegate { return true; }
vkrzv

2
Esteja ciente dos riscos potenciais associados a esta abordagem. Consulte stackoverflow.com/a/6613434/2969615 para obter mais informações.
Joe Coyle

19

Este link é do seu interesse: http://msdn.microsoft.com/en-us/library/ds8bxk2a.aspx

Para conexões http, as classes WebRequest e WebResponse usam SSL para se comunicar com hosts da web que oferecem suporte a SSL. A decisão de usar SSL é feita pela classe WebRequest, com base no URI fornecido. Se o URI começar com "https:", o SSL será usado; se o URI começar com "http:", será usada uma conexão não criptografada.


Ótimo link. Essa é uma distinção importante.
DanM7 de

1
Sua resposta implica que o código da pergunta deve funcionar?
Rowland Shaw

18

Este funcionou para mim:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

1
O valor padrão é "Ssl2 | Tls". Eu tinha habilitado apenas Tls 1.1 e 1.2 em meu servidor. Isso realmente resolveu o problema! Para LetsEncrypt com nginX no linux, os protocolos são definidos aqui: /etc/letsencrypt/options-ssl-nginx.conf
Jerther

Acredito que se trate de uma questão diferente. Não se trata de certificados inválidos, mas de versões superiores de TLS.
wp78de

Eu estava recebendo "Uma conexão existente foi fechada à força pelo host remoto" e essa solução funcionou para mim
oamilkar

Observe que esta é uma configuração global, portanto, você só precisa fazer isso uma vez e não toda vez que configurar a solicitação.
Chad Hedgcock

Posso fazer isso para uma única solicitação de alguma forma? Parece que ServicePointManager é algo bastante global ...
wexman
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.