[C#] HttpClient를 사용하여 Https 호출

내가 사용하고 HttpClientC #을 사용 WebApi 호출을 만들기위한. 에 비해 깔끔하고 빠른 방법으로 보입니다 WebClient. 그러나 Https전화를 걸 때 멈춰 있습니다.

아래 코드를 작성하여 Https전화를 걸 수 있습니까?

HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("https://foobar.com/");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/xml"));

var task = httpClient.PostAsXmlAsync<DeviceRequest>(
                "api/SaveData", request);

편집 1 :
위 코드는 http 호출을 위해 잘 작동합니다. 그러나 스키마를 https로 변경하면 작동하지 않습니다. 얻은 오류는 다음과 같습니다.

기본 연결이 닫혔습니다. SSL / TLS 보안 채널에 대한 신뢰 관계를 설정할 수 없습니다.

편집 2 :
체계를 https로 변경하는 것은 1 단계입니다.

C # 요청과 함께 인증서 및 공개 / 개인 키를 제공하는 방법



답변

서버가 TLS 1.2와 같은 상위 TLS 버전 만 지원하는 경우 클라이언트 PC가 기본적으로 더 높은 TLS 버전을 사용하도록 구성되어 있지 않으면 여전히 실패합니다. 이 문제를 극복하려면 코드에 다음을 추가하십시오.

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

예제 코드를 수정하면 다음과 같습니다.

HttpClient httpClient = new HttpClient();   

//specify to use TLS 1.2 as default connection
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

httpClient.BaseAddress = new Uri("https://foobar.com/");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

var task = httpClient.PostAsXmlAsync<DeviceRequest>("api/SaveData", request);


답변

URI에 HTTPS를 지정하기 만하면됩니다.

new Uri("https://foobar.com/");

Foobar.com에는 신뢰할 수있는 SSL 인증서가 있어야합니다. 그렇지 않으면 신뢰할 수없는 오류로 통화가 실패합니다.

편집 답변 : HttpClient를 사용한 ClientCertificates

WebRequestHandler handler = new WebRequestHandler();
X509Certificate2 certificate = GetMyX509Certificate();
handler.ClientCertificates.Add(certificate);
HttpClient client = new HttpClient(handler);

편집 답변 2 : 연결중인 서버에서 SSL, TLS 1.0 및 1.1을 비활성화 한 상태에서 .NET Framework 4.5 (또는 그 이하)를 계속 실행중인 경우 선택해야합니다.

  1. .Net 4.6+로 업그레이드 ( 기본적으로 TLS 1.2 지원 )
  2. TLS1.2를 통해 연결 4.5을 지시하는 레지스트리 변경 추가 (참조 : 세일즈 포스 작성자 의 compat 변경 또는 체크 아웃에 키 IISCrypto 로널드 라모스 참조 대답 코멘트 )
  3. TLS1.2를 통해 연결하도록 .NET을 수동으로 구성하는 응용 프로그램 코드 추가 (Ronald Ramos 답변 참조 )

답변

다음과 같이 코드를 수정해야합니다.

httpClient.BaseAddress = new Uri("https://foobar.com/");

https:URI 체계 만 사용하면 됩니다. MSDN에는 보안 HTTP 연결에 대한 유용한 페이지가 있습니다 . 과연:

https : URI 체계를 사용하십시오.

HTTP 프로토콜은 두 가지 URI 체계를 정의합니다.

http : 암호화되지 않은 연결에 사용됩니다.

https : 암호화해야하는 보안 연결에 사용됩니다. 이 옵션은 또한 디지털 인증서 및 인증 기관을 사용하여 서버가 누구인지 확인합니다.

또한 HTTPS 연결이 SSL 인증서를 사용하는 것을 고려하십시오. 보안 연결에이 인증서가 있는지 확인하십시오. 그렇지 않으면 요청이 실패합니다.

편집하다:

위의 코드는 http 호출에 적합합니다. 그러나 스키마를 https로 변경하면 작동하지 않습니다. 오류를 게시하십시오.

작동하지 않는 것은 무엇을 의미합니까? 요청이 실패 했습니까? 예외가 발생합니까? 질문을 명확하게하십시오.

요청이 실패하면 SSL 인증서 여야합니다.

문제를 해결하기 위해 클래스 HttpWebRequest와 해당 속성을 사용할 수 있습니다 ClientCertificate. 또한 인증서를 사용하여 HTTPS 요청을하는 방법에 대한 유용한 샘플을 여기 에서 찾을 수 있습니다 .

예는 다음과 같습니다 (이전 링크 된 MSDN 페이지에 표시됨).

//You must change the path to point to your .cer file location. 
X509Certificate Cert = X509Certificate.CreateFromCertFile("C:\\mycert.cer");
// Handle any certificate errors on the certificate from the server.
ServicePointManager.CertificatePolicy = new CertPolicy();
// You must change the URL to point to your Web server.
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://YourServer/sample.asp");
Request.ClientCertificates.Add(Cert);
Request.UserAgent = "Client Cert Sample";
Request.Method = "GET";
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();


답변

연결할 https때이 오류가 발생하기 전에이 줄을 추가 HttpClient httpClient = new HttpClient();하고 성공적으로 연결하십시오.

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

나는 이 답변다른 유사한 답변 에서 그것을 알고 있으며 언급은 다음과 같습니다.

이것은 개발에 유용한 해킹이므로 #if DEBUG #endif 문을 주위에 두는 것이 가장 안전합니다.

또한, 다른 답변 에서 인증서 를 사용 new X509Certificate()하거나 new X509Certificate2()인증서를 만드는 방법을 시도하지 않았지만 단순히 작성하여 new()작동 하는지 확실 하지 않습니다.

편집 : 일부 참조 :

IIS 7에서 자체 서명 된 서버 인증서 만들기

IIS 7에서 SSL 인증서 가져 오기 및 내보내기

.pfx를 .cer로 변환

ServerCertificateValidationCallback 사용을위한 모범 사례

지문 값이 다음과 같습니다 x509certificate.GetCertHashString().

인증서의 지문 검색


답변

사용자 에이전트가 필요한 GitHub에 연결할 때도 같은 문제가 발생했습니다. 따라서 인증서를 생성하지 않고이를 제공하는 것으로 충분합니다.

var client = new HttpClient();

client.BaseAddress = new Uri("https://api.github.com");
client.DefaultRequestHeaders.Add(
    "Authorization",
    "token 123456789307d8c1d138ddb0848ede028ed30567");
client.DefaultRequestHeaders.Accept.Add(
    new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add(
    "User-Agent",
    "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36");


답변

다음과 같은 수준에 비전 역 설정이 있습니다 HttpClientHandler.

var handler = new HttpClientHandler()
{
    SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
};

var client = new HttpClient(handler);

따라서 최신 TLS 버전을 사용할 수 있습니다.

기본값 SslProtocols.Default은 실제로 SslProtocols.Ssl3 | SslProtocols.Tls(.Net Core 2.1 및 .Net Framework 4.7.1에서 확인 됨)입니다.


답변

URI에서 HTTPS를 지정하면 트릭을 수행해야합니다.

httpClient.BaseAddress = new Uri("https://foobar.com/");

요청이 HTTP에서는 작동하지만 HTTPS에서는 실패하는 것이 가장 확실한 것은 인증서 문제 입니다. 호출자가 인증서 발행자를 신뢰하고 인증서가 만료되지 않았는지 확인하십시오. 이를 확인하는 빠르고 쉬운 방법은 브라우저에서 쿼리를 작성하는 것입니다.

또한 서버에서 HTTPS 요청을 올바르게 제공하도록 설정되어 있는지 (서버의 경우 및 / 또는 가능한 경우) 확인할 수도 있습니다.