C#客戶端HttpClient請求認證及數(shù)據(jù)傳輸
一,授權(quán)認證
客戶端請求服務(wù)器時,需要通過授權(quán)認證許可,方能獲取服務(wù)器資源,目前比較常見的認證方式有 Basic 、JWT、Cookie。
HttpClient 是 C# 中的 HTTP/HTTPS 客戶端,用于發(fā)送 HTTP 請求和接收來自通過 URI 確認的資源的 HTTP 響應(yīng)。下面以具體代碼做示范。
1. 基礎(chǔ)認證示例
// Basic基礎(chǔ)認證 public async Task Basic(string user, string password, string url) { // 如果認證頁面是 https 的,請參考一下 jwt 認證的 HttpClientHandler // 創(chuàng)建 client HttpClient client = new HttpClient(); // 創(chuàng)建身份認證 // using System.Net.Http.Headers; AuthenticationHeaderValue authentication = new AuthenticationHeaderValue( "Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{user}:{password}") )); client.DefaultRequestHeaders.Authorization = authentication; byte[] response = await client.GetByteArrayAsync(url); client.Dispose(); }
可以看到 Basic 認證的安全程度非常低,多用于路由器和嵌入式設(shè)備,而且往往不會使用 HTTPS。
2. JWT 認證示例
// Jwt認證 public async Task Bearer(string token, string url) { // HttpClientHandler及其派生類使開發(fā)人員能夠配置各種選項, 包括從代理到身份驗證。 // helpLink https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclienthandler?view=netframework-4.8 var httpclientHandler = new HttpClientHandler(); // 如果服務(wù)器有 https 證書,但是證書不安全,則需要使用下面語句 // => 也就是說,不校驗證書,直接允許 httpclientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true; using (var httpClient = new HttpClient(httpclientHandler)) { // 創(chuàng)建身份認證 // System.Net.Http.Headers.AuthenticationHeaderValue; httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); await httpClient.GetAsync(url); httpClient.Dispose(); } }
JWT 認證,需要客戶端攜帶 token ,token 是一段加密過的字符串,關(guān)于原理這里不多說,token 是通過客戶端 header 攜帶的。
另外,對于測試的 Web 應(yīng)用或者內(nèi)網(wǎng)應(yīng)用, HTTPS 證書可能不是公網(wǎng)國際認證的證書,就需要跳過認證,直接允許訪問使用。
var httpclientHandler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true, };
3. Cookie 示例
HttpClient 中,Cookie 有兩種處理方式。
一種是已經(jīng)知道 Cookie ,直接將 Cookie 存儲到 HttpClient 中;另一種是還沒有 Cookie ,通過賬號密碼登錄獲取到 Cookie ,自動存儲到 HttpClient 對象中,接著使用當前 HttpClient 對象請求 URL。
兩種方式的設(shè)定,是通過 HttpClientHandler 的 UseCookies 屬性設(shè)置的。
示例
var httpclientHandler = new HttpClientHandler() { UseCookies = true };
? UseCookies 獲取或設(shè)置一個值,該值指示處理程序是否使用 CookieContainer 屬性存儲服務(wù)器 Cookie,并在發(fā)送請求時使用這些 Cookie。
方式1:
// 先用賬號密碼登陸再請求 public async Task Cookie(string user, string password, string loginUrl, string url) { var httpclientHandler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true, UseCookies = true }; // 如果服務(wù)器有 https 證書,但是證書不安全,則需要使用下面語句 // => 也就是說,不校驗證書,直接允許 var loginContent = new FormUrlEncodedContent(new[] { new KeyValuePair<string,string>("user",user), new KeyValuePair<string, string>("password",password) }); using (var httpClient = new HttpClient(httpclientHandler)) { // 先登陸 var result = await httpClient.PostAsync(loginUrl, loginContent); // 登陸成功后,客戶端會自動攜帶 cookie ,不需要再手動添加 //if (result.IsSuccessStatusCode) //{ // /* // * 如果請求成功 // */ //} var result2 = await httpClient.GetAsync(url); // httpclient 已經(jīng)攜帶 Cookie ,可以多次使用 // var result3 = await httpClient.GetAsync(url3); // var result4 = await httpClient.GetAsync(url4); httpClient.Dispose(); } }
方式2:
//已經(jīng)拿到 cookie ,直接使用 cookie 請求 public async Task Cookie(string cookie, string url) { var httpclientHandler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true, UseCookies = false }; // 如果服務(wù)器有 https 證書,但是證書不安全,則需要使用下面語句 // => 也就是說,不校驗證書,直接允許 using (var httpClient = new HttpClient(httpclientHandler)) { httpClient.DefaultRequestHeaders.Add("Cookie", cookie); await httpClient.GetAsync(url); httpClient.Dispose(); } }
二,請求類型
HTTP 請求里,有 GET、POST、DELETE、PUT 等請求方式。
HttpClient 中,有以下請求相關(guān)的方法
- CancelPendingRequests
- DeleteAsync
- GetAsync
- GetByteArrayAsync
- GetStreamAsync
- GetStringAsync
- PostAsync
- PutAsync
- SendAsync
其中, CancelPendingRequests 是取消該實例所有掛起的請求,不是請求類型。
SendAsync 用于處理送 HttpRequestMessage(表示一條 HTTP 請求消息),比較原生。
對于 GetAsync、PostAsync等請求方法,使用過程類似,下面是使用示例
public async void Request(string url) { using (var httpClient = new HttpClient()) { // HttpClient 中,所有 Get 請求都是異步的 HttpResponseMessage result = await httpClient.GetAsync(url); // Task<>.Result 可以獲取異步結(jié)果 result = httpClient.GetAsync(url).Result; //var result1 = await httpClient.GetByteArrayAsync(url); //var result1 = await httpClient.GetStreamAsync(url); //var result1 = await httpClient.GetStringAsync(url); // ByteArrayContent FormUrlEncodedContent fromContent = new FormUrlEncodedContent(new[] { new KeyValuePair<string,string>("Email","123@qq.com"), new KeyValuePair<string, string>("Number","666") }); // 使用 Post ,必須攜帶 繼承 HttpContent 的對象 // 就是說,Post 必須要上傳數(shù)據(jù) result = await httpClient.PostAsync(url, fromContent); // 如果沒有數(shù)據(jù)要上傳,可以使用 null result = await httpClient.PostAsync(url, null); httpClient.Dispose(); }
三,數(shù)據(jù)傳輸
HTTP/HTTPS 請求中,往往隨著數(shù)據(jù)傳輸,例如表單提交、JSON上傳、文件上傳等,下面以代碼示范。
1. Query
ASP.NET Core API 可以這樣寫
[HttpPost("aaa")] public async Task<JsonResult> AAA(int? a, int? b) { if (a == null || b == null) return new JsonResult(new { code = 0, result = "aaaaaaaa" }); return new JsonResult(new { code = 2000, result = a + "|" + b }); }
HttpClient
// URL Query 參數(shù) public void Query(string a, string b) { var httpclientHandler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true, }; using (var httpClient = new HttpClient(httpclientHandler)) { var result = httpClient.PostAsync($"https://localhost:5001/test?a={a}&b=", null).Result; httpClient.Dispose(); } }
2. Header
Header 是以鍵值形式存儲的,HttpClient 示例
// Header 頭 public void Header() { var httpclientHandler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true, }; using (var httpClient = new HttpClient(httpclientHandler)) { httpClient.DefaultRequestHeaders.Add("MyEmail", "123@qq.com"); var result = httpClient.GetAsync($"https://localhost:5001/test").Result; httpClient.Dispose(); } }
ASP.NET Core API 示例
[HttpPost("ddd")] public async Task<JsonResult> DDD([FromHeader]int? a, [FromHeader]int? b) { if (a == null || b == null) return new JsonResult(new { code = 0, result = "aaaaaaaa" }); return new JsonResult(new { code = 200, result = a + "|" + b }); }
3. 表單
// 表單提交 // application/x-www-form-urlencoded public void From() { var httpclientHandler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true, }; var fromContent = new FormUrlEncodedContent(new[] { new KeyValuePair<string,string>("Id","1"), new KeyValuePair<string,string>("Name","癡者工良"), new KeyValuePair<string, string>("Number","666666") }); using (var httpClient = new HttpClient(httpclientHandler)) { var result = httpClient.PostAsync("https://localhost:5001/test", fromContent).Result; Console.WriteLine(result.Content.ReadAsStringAsync().Result); httpClient.Dispose(); } }
4. JSON
除了 JSON ,還有
- text/html
- application/javascript
- text/plain
- application/xml
他們都是使用 StringContent 來表示。
// Json 等 public void StringAnd(string json) { var httpclientHandler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true, }; var jsonContent = new StringContent(json); // Json 是 StringContent,上傳時要指定 Content-Type 屬性,除此外還有 // text/html // application/javascript // text/plain // application/xml jsonContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); using (var httpClient = new HttpClient(httpclientHandler)) { var result = httpClient.PostAsync("https://localhost:5001/test", jsonContent).Result; Console.WriteLine(result.Content.ReadAsStringAsync().Result); httpClient.Dispose(); } }
5. 上傳文件
API 這樣寫
[HttpPost] //上傳文件是 post 方式,這里加不加都可以 public async Task<IActionResult> UploadFiles(List<IFormFile> files) { // ... }
HttpClient 寫法
// 上傳文件 public async Task File(string filepath, string fromName, string url) { using (var client = new HttpClient()) { FileStream imagestream = System.IO.File.OpenRead(filepath); // multipartFormDataContent.Add(); var multipartFormDataContent = new MultipartFormDataContent() { { new ByteArrayContent(System.IO.File.ReadAllBytes(filepath)), // 文件流 fromName, // 對應(yīng) 服務(wù)器 WebAPI 的傳入?yún)?shù) Path.GetFileName(filepath) // 上傳的文件名稱 } }; /* * 如果服務(wù)器 API 寫法是 * ([FromForm]IFromFile files) * 那么上面的 fromName="files" */ // multipartFormDataContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data"); HttpResponseMessage response = await client.PostAsync(url, multipartFormDataContent); if (!response.IsSuccessStatusCode) { Console.WriteLine("up image error"); Console.WriteLine(response.RequestMessage); } } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#實現(xiàn)延時并自動關(guān)閉MessageBox的方法
這篇文章主要介紹了C#實現(xiàn)延時并自動關(guān)閉MessageBox的方法,非常實用的功能,需要的朋友可以參考下2014-08-08C#實現(xiàn)通過ffmpeg從flv視頻文件中截圖的方法
這篇文章主要介紹了C#實現(xiàn)通過ffmpeg從flv視頻文件中截圖的方法,實例分析了C#使用ffmpeg操作flv文件的技巧,需要的朋友可以參考下2015-03-03用C#對ADO.NET數(shù)據(jù)庫完成簡單操作的方法
用C#對ADO.NET數(shù)據(jù)庫完成簡單操作的方法...2007-03-03