C#客户端HttpClient请求认证及数据传输
作者:痴者工良 发布时间:2023-06-11 21:11:00
一,授权认证
客户端请求服务器时,需要通过授权认证许可,方能获取服务器资源,目前比较常见的认证方式有 Basic 、JWT、Cookie。
HttpClient 是 C# 中的 HTTP/HTTPS 客户端,用于发送 HTTP 请求和接收来自通过 URI 确认的资源的 HTTP 响应。下面以具体代码做示范。
1. 基础认证示例
// Basic基础认证
public async Task Basic(string user, string password, string url)
{
// 如果认证页面是 https 的,请参考一下 jwt 认证的 HttpClientHandler
// 创建 client
HttpClient client = new HttpClient();
// 创建身份认证
// 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 认证的安全程度非常低,多用于路由器和嵌入式设备,而且往往不会使用 HTTPS。
2. JWT 认证示例
// Jwt认证
public async Task Bearer(string token, string url)
{
// HttpClientHandler及其派生类使开发人员能够配置各种选项, 包括从代理到身份验证。
// helpLink https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclienthandler?view=netframework-4.8
var httpclientHandler = new HttpClientHandler();
// 如果服务器有 https 证书,但是证书不安全,则需要使用下面语句
// => 也就是说,不校验证书,直接允许
httpclientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true;
using (var httpClient = new HttpClient(httpclientHandler))
{
// 创建身份认证
// System.Net.Http.Headers.AuthenticationHeaderValue;
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
await httpClient.GetAsync(url);
httpClient.Dispose();
}
}
JWT 认证,需要客户端携带 token ,token 是一段加密过的字符串,关于原理这里不多说,token 是通过客户端 header 携带的。
另外,对于测试的 Web 应用或者内网应用, HTTPS 证书可能不是公网国际认证的证书,就需要跳过认证,直接允许访问使用。
var httpclientHandler = new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,
};
3. Cookie 示例
HttpClient 中,Cookie 有两种处理方式。
一种是已经知道 Cookie ,直接将 Cookie 存储到 HttpClient 中;另一种是还没有 Cookie ,通过账号密码登录获取到 Cookie ,自动存储到 HttpClient 对象中,接着使用当前 HttpClient 对象请求 URL。
两种方式的设定,是通过 HttpClientHandler 的 UseCookies 属性设置的。
示例
var httpclientHandler = new HttpClientHandler()
{
UseCookies = true
};
UseCookies 获取或设置一个值,该值指示处理程序是否使用 CookieContainer 属性存储服务器 Cookie,并在发送请求时使用这些 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
};
// 如果服务器有 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 已经携带 Cookie ,可以多次使用
// var result3 = await httpClient.GetAsync(url3);
// var result4 = await httpClient.GetAsync(url4);
httpClient.Dispose();
}
}
方式2:
//已经拿到 cookie ,直接使用 cookie 请求
public async Task Cookie(string cookie, string url)
{
var httpclientHandler = new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,
UseCookies = false
};
// 如果服务器有 https 证书,但是证书不安全,则需要使用下面语句
// => 也就是说,不校验证书,直接允许
using (var httpClient = new HttpClient(httpclientHandler))
{
httpClient.DefaultRequestHeaders.Add("Cookie", cookie);
await httpClient.GetAsync(url);
httpClient.Dispose();
}
}
二,请求类型
HTTP 请求里,有 GET、POST、DELETE、PUT 等请求方式。
HttpClient 中,有以下请求相关的方法
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 可以获取异步结果
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 必须要上传数据
result = await httpClient.PostAsync(url, fromContent);
// 如果没有数据要上传,可以使用 null
result = await httpClient.PostAsync(url, null);
httpClient.Dispose();
}
三,数据传输
HTTP/HTTPS 请求中,往往随着数据传输,例如表单提交、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 参数
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={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, // 对应 服务器 WebAPI 的传入参数
Path.GetFileName(filepath) // 上传的文件名称
}
};
/*
* 如果服务器 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);
}
}
}
来源:https://www.cnblogs.com/whuanle/p/11656734.html


猜你喜欢
- 方法一:需要调用win32api,winform、wpf通用[DllImport("user32.dll")]publi
- 这篇文章主要介绍了Spring配置文件如何使用${username},文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习
- springboot引入外部yml配置文件当需要在springboot中引用其他的yml文件时,需要在application.yml里配置s
- 介绍Java中的享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享尽可能多的对象来减少内存占用和提高性能.Ja
- 一、代码@Componentpublic class BService { @Autowired &
- 本文实例讲述了C#精确计算年龄的方法。分享给大家供大家参考。具体如下:该源码在vs2010测试通过using System;using Sy
- 本文实例讲述了简单记事本java实现代码。分享给大家供大家参考。具体如下:完整代码如下:import java.awt.*;import j
- 我们都知道现在的语音合成TTS是可以通过微软的SAPI实现的,好处我就不多说了,方便而已,因为在微软的操作系统里面就自带了这个玩意,主要的方
- jdk下载并配置下载jdk下图是自己资源管理器中jdk的安装路径,双击然后next就好,不需要改什么配置手里没有安装包的,下载地址在这里 :
- 一、多线程的优缺点多线程的优点:1)资源利用率更好2)程序设计在某些情况下更简单3)程序响应更快多线程的代价:1)设计更复杂虽然有一些多线程
- 网上找了一些获取客户端IP的方法,但本地测试时,返回的是IPv6的表示方法"::1":Host文件里面:# &
- 逆时针画圆弧,原理:将360度分割成36份,分别标出每10度角度时的坐标点,然后将每个点连接起来。 #include <io
- 在C#中,用于存储的结构较多,如:DataTable,DataSet,List,Dictionary,Stack等
- HttpServletRequest介绍HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HT
- 环境搭建创建Maven项目。pom.xml文件中引入RocketMQ依赖。<dependencies>  
- 项目描述: springboot+springcloud+zookeeper+eureka+maven;为多模块多module的分布式架构;
- 本文研究的主要是Java面试题中的一个比较常见的题目,判断及防止SQL注入的问题,具体介绍如下。SQL注入是目前黑客最常用的攻击手段,它的原
- 因工作需要,经常跟时间戳打交道,但是因为它仅仅是一个数字,我们很难直接看出它有什么意义,或两个时间戳之间究竟差了多长的间隔。于是从MSDN
- 本文实例讲述了Android编程实现Toast只显示最后一条的方法。分享给大家供大家参考,具体如下:在做Android开发中,时不时的可能会
- 目录引言API介绍1、Optional(),empty(),of(),ofNullable()2、orElse(),orElseGet()和