HttpClient를 사용하여 Https 호출


157

내가 사용하고 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 # 요청과 함께 인증서 및 공개 / 개인 키를 제공하는 방법


2
다음을 지정하여 https 전화를 걸고 있습니다new Uri("https://foobar.com/");
felickz

2
혼란 스러워요. 아직 작동하지 않습니까? 오류가 발생 했습니까? (편집 : OP가 https에서 http로 URI를 변경하기 전에 게시)
Tim

답변:


215

서버가 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);

@DerekS Am 기쁘게 생각합니다. 어떤 이유로 프로덕션 설정에서 코드를 수정할 수 없지만 서버에서 일부 관리자를 수행 할 수있는 경우이 유틸리티를 사용하여 TLS 1.2를 기본값으로 구성합니다. nartac.com/Products/IISCrypto
Ronald Ramos

SecurityProtocolType.Tls12당신이 언급 한 그 열거 값을 찾을 수 couldnt한다
JobaDiniz

1
@JobaDiniz는 .NET 4.5 이상을 사용하며 System.Net 네임 스페이스를 포함합니다.
Ronald Ramos

SecurityProtocol 설정은 한 번만 수행해야합니까? 응용 프로그램을 시작할 때처럼?
CamHart

이것은 잘 작동합니다. 감사. 나는 또한이 HttpClient client = new HttpClient (); 사용 된 헤더를 지우지 않아도된다는 것을 알았습니다. ServicePointManager.SecurityProtocol = 보안 프로토콜 유형 .Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; HttpResponseMessage 응답 = await client.GetAsync ( "https : // ...");
AtLeastTheresToast 2016 년

127

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 답변 참조 )

@felickz 큰 반응. Windows Phone 8의 WebRequestHandler 라이브러리와 동등한 것이 있습니까?
Billatron

WP / Win8에 대한 @Billatron 다른 라이브러리 .. 참조
felickz

6
자체 서명 된 인증서를 개발하거나 처리 할 때 다음과 같은 경우 신뢰할 수없는 인증서 오류를 무시할 수 있습니다. ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
개발자

6
무엇입니까 GetMyX509Certificate?
Fandi Susanto

6
@developer는 코드가 프로덕션 빌드에 들어 가지 않기를 희망합니다. :)
felickz

15

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

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();

트릭은 요청과 함께 인증서를 보내는 데 있습니다. 그렇게하는 방법?
Abhijeet

"C : \\ mycert.cer"는 어디서 구할 수 있습니까? mycert.cer 파일을 생성하는 방법?
masiboo

@masiboo 내가 쓴 내용은 HTTPS 호출 방법에 대한 답변입니다. * .cer 파일을 생성하는 방법에 대해 Google에 문의하면 직접 답변을 찾을 수 있습니다.
Alberto Solano

9

연결할 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().

인증서의 지문 검색


6

사용자 에이전트가 필요한 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");

2
인터넷과 공유하고있는 토큰을 취소해야합니다. GitHub가 자동으로 수행 한 것 같습니다.
Amias

21
당신은 정말로 내 토큰으로 시작한다고 생각합니까 123456789??
Carlo V. Dango

5

다음과 같은 수준에 비전 역 설정이 있습니다 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에서 확인 됨)입니다.


답변 해주셔서 감사합니다. 약간의 참고 사항 :이 문서에 따르면 docs.microsoft.com/en-us/dotnet/api/… 최소한 4.7.1 프레임 워크가 필요합니다.
GELR

@GELR 예, 그렇습니다. 위의 코드는 .Net 4.6.1에서 런타임 오류를 발생시킵니다. 답변을 수정했습니다.
중지 크랜

.NET Framework의 이전 버전에서이 속성은 비공개입니다
JotaBe

Net Core 3.1에서는 이것이 나를 위해 일한 전부입니다. 전역 System.Net.ServicePointManager.SecurityProtocol = xxx를 설정하면 패킷 추적에 전혀 영향을 미치지 않습니다.
로완 스미스

3

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

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

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

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


: 비슷한 문제가 있습니다. 브라우저에서 쿼리를했는데 인증서가 유효합니다 (통화가 통과하고 서비스 수준으로 인증되며 모든 것이 매력처럼 작동합니다).하지만 프로그래밍 방식으로는 작동하지 않습니다. 다른 무엇을 할 수 있습니까? srvice를 프로그래밍 방식으로 호출하는 웹 응용 프로그램과 "브라우저 수동으로 서비스 호출"브라우저에서 정확히 동일한 인증서를 사용하는 경우
Carlos

2

또한 오류가 발생했습니다.

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

... TLS 1.3 이 필요한 API 공급자에게 리소스를 요청하려는 Xamarin Forms Android 대상 응용 프로그램 사용

해결책은 프로젝트 구성을 업데이트하여 Xamarin "managed"(. NET) http 클라이언트 (Xamarin Forms v2.5에서 TLS 1.3을 지원하지 않음)를 바꾸고 대신 Android 기본 클라이언트를 사용하는 것입니다.

Visual Studio에서 간단한 프로젝트 토글입니다. 아래 스크린 샷을 참조하십시오.

  • 프로젝트 속성
  • 안드로이드 옵션
  • 많은
  • 아이템 목록
  • "HttpClient 구현"을 "Android"로 변경
  • SSL / TLS 구현을 "Native TLS 1.2+"로 변경

여기에 이미지 설명을 입력하십시오


1

클래스에 아래 선언을 추가하십시오.

public const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
public const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;

후:

var client = new HttpClient();

과:

ServicePointManager.SecurityProtocol = Tls12;
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 /*| SecurityProtocolType.Tls */| Tls12;

행복? :)


1

나는이 문제가 있었고 내 경우에는 솔루션이 어리석게 간단했습니다 : 관리자 권한으로 Visual Studio를 엽니 다. 위의 모든 솔루션을 시도했지만이 작업을 수행 할 때까지 작동하지 않았습니다. 누군가 소중한 시간을 절약하기를 바랍니다.


사이트를 처음 사용하기 때문에 답변 옆에 녹색 확인 표시가 있으면 OP에서 문제에 대한 올바른 솔루션으로 승인 한 것입니다. 더 좋고 더 완전한 답변을 줄 수 없다면, 특히 오래된 질문에 대해 다른 답변을 제출하지 않는 것이 가장 좋습니다.
Sam W

4
글쎄, 나도 문제가 있었고 녹색 확인 답변은 전혀 도움이되지 못했습니다. 나에게 도움이되는 대안 솔루션을 제공한다고 생각했지만 다음 번에는 그렇게하지 않을 것입니다. 마이너스 포인트 주셔서 감사합니다;) 좋은 하루 되세요.
Lucian Satmarean

0

ModernHttpClient Nuget 패키지를 사용해 볼 수 있습니다 : 패키지를 다운로드 한 후 다음과 같이 구현할 수 있습니다 :

 var handler = new ModernHttpClient.NativeMessageHandler()
 {
     UseProxy = true,
 };


 handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
 handler.PreAuthenticate = true;
 HttpClient client = new HttpClient(handler);

불행히도, 이것은 나에게서 작동하지 않았습니다. 해결책은 xamarin 관리 http 클라이언트에서 android-native http 클라이언트로 전환하여 TLS 1.3을 활성화하는 것입니다. 아래 답변을 참조하십시오.
MSC

0

felickz에 동의하지만 C #의 사용법을 명확히하기위한 예를 추가하고 싶습니다. 다음과 같이 Windows 서비스에서 SSL을 사용합니다.

    var certificatePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin");
    gateway = new GatewayService();
    gateway.PreAuthenticate = true;


    X509Certificate2 cert = new X509Certificate2(certificatePath + @"\Attached\my_certificate.pfx","certificate_password");
    gateway.ClientCertificates.Add(cert);

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
    gateway.UserAgent = Guid.NewGuid().ToString();
    gateway.Timeout = int.MaxValue;

웹 응용 프로그램에서 사용하려는 경우 프록시 측의 구현을 다음과 같이 변경합니다.

public partial class GatewayService : System.Web.Services.Protocols.SoapHttpClientProtocol // to => Microsoft.Web.Services2.WebServicesClientProtocol

-4

오류의 경우 :

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

다음 코드를 사용하여 무조건 인증서를 수락해야한다고 생각합니다.

ServicePointManager.ServerCertificateValidationCallback += 
    (sender, cert, chain, sslPolicyErrors) => true;

같은 대립적는 질문에 그의 대답에 쓴 SSL 웹 API에 연결하는 .NET 클라이언트 .


4
이것은 인증서 유효성 검사를 무시하는 것입니다. 프로덕션에서이 작업을 수행하지 마십시오.
존 Korsnes

글쎄, @JohnKorsnes, Abhijeet이 공개 WebAPI 서버에 액세스하면 그가 그것에 대해 많은 것을 할 수 있다고 생각하지 않습니다. 이것이 나의 경우였다.
Nemanja Simović
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.