HttpClient를 사용하여 Https 호출
내가 사용하고 HttpClient
C #을 사용 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 (또는 그 이하)를 계속 실행중인 경우 선택해야합니다.
- .Net 4.6+로 업그레이드 ( 기본적으로 TLS 1.2 지원 )
- 4.5에서 TLS1.2를 통해 연결하도록 지시하는 레지스트리 변경 사항 추가 (참조 : compat 및 키를 변경하기 위해 compat 및 키에 대한 salesforce 쓰기 또는 IISCryp를 참조하여 Ronald Ramos 답변 설명 참조 )
- 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();
사용자 에이전트가 필요한 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");
연결할 https
때이 오류가 발생하기 전에이 줄을 추가 HttpClient httpClient = new HttpClient();
하고 성공적으로 연결하십시오.
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
나는 이 답변 과 다른 유사한 답변 에서 그것을 알고 있으며 언급은 다음과 같습니다.
이것은 개발에 유용한 해킹이므로 #if DEBUG #endif 문을 주위에 두는 것이 가장 안전합니다.
또한, 다른 답변 에서 인증서 를 사용 new X509Certificate()
하거나 new X509Certificate2()
인증서를 만드는 방법을 시도하지 않았지만 단순히 작성하여 new()
작동 하는지 확실 하지 않습니다.
EDIT: Some References:
Create a Self-Signed Server Certificate in IIS 7
Import and Export SSL Certificates in IIS 7
Best practices for using ServerCertificateValidationCallback
I find value of Thumbprint is equal to x509certificate.GetCertHashString()
:
Retrieve the Thumbprint of a Certificate
Just specifying HTTPS in the URI should do the trick.
httpClient.BaseAddress = new Uri("https://foobar.com/");
If the request works with HTTP but fails with HTTPS then this is most certainly a certificate issue. Make sure the caller trusts the certificate issuer and that the certificate is not expired. A quick and easy way to check that is to try making the query in a browser.
You also may want to check on the server (if it's yours and / or if you can) that it is set to serve HTTPS requests properly.
I was also getting the error:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
... with a Xamarin Forms Android-targeting application attempting to request resources from an API provider that required TLS 1.3.
The solution was to update the project configuration to swap out the Xamarin "managed" (.NET) http client (that doesn't support TLS 1.3 as of Xamarin Forms v2.5), and instead use the android native client.
It's a simple project toggle in visual studio. See screenshot below.
- Project Properties
- Android Options
- Advanced
- List item
- Change "HttpClient implementation" to "Android"
- Change SSL/TLS implementation to "Native TLS 1.2+"
There is a non-global setting at the level of HttpClientHandler
:
var handler = new HttpClientHandler()
{
SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
};
var client = new HttpClient(handler);
Thus one enables latest TLS versions.
Note, that the default value SslProtocols.Default
is actually SslProtocols.Ssl3 | SslProtocols.Tls
(checked for .Net Core 2.1 and .Net Framework 4.7.1).
Add the below declarations to your class:
public const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
public const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;
After:
var client = new HttpClient();
And:
ServicePointManager.SecurityProtocol = Tls12;
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 /*| SecurityProtocolType.Tls */| Tls12;
Happy? :)
You can try using the ModernHttpClient Nuget Package: After downloading the package, you can implement it like this:
var handler = new ModernHttpClient.NativeMessageHandler()
{
UseProxy = true,
};
handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
handler.PreAuthenticate = true;
HttpClient client = new HttpClient(handler);
I agree with felickz but also i want to add an example for clarifying the usage in c#. I use SSL in windows service as follows.
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;
If I'm going to use it in a web application, I'm just changing the implementation on the proxy side like this:
public partial class GatewayService : System.Web.Services.Protocols.SoapHttpClientProtocol // to => Microsoft.Web.Services2.WebServicesClientProtocol
I had this issue and in my case the solution was stupidly simple: open Visual Studio with Administrator rights. I tried all the above solutions and it didn't work until I did this. Hope it saves someone some precious time.
For error:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
I think that you need to accept certificate unconditionally with following code
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
as Oppositional wrote in his answer to question .NET client connecting to ssl Web API.
참고URL : https://stackoverflow.com/questions/22251689/make-https-call-using-httpclient
'Programing' 카테고리의 다른 글
DateTimePicker : 날짜와 시간을 모두 선택 (0) | 2020.06.23 |
---|---|
iOS 5.1 SDK의 iPad 시뮬레이터에 "홈"버튼이없는 이유는 무엇입니까? (0) | 2020.06.23 |
날짜를 타임 스탬프로 변환하는 방법? (0) | 2020.06.22 |
JavaScript를 사용하여 선택한 HTML 옵션을 어떻게 변경합니까? (0) | 2020.06.22 |
grep -f와 동등한 PowerShell (0) | 2020.06.22 |