使用http请求中 如何使用token添加到http请求头部
核心区别请求头 vs 内容头这是一个非常关键的区别让我用HTTP报文的实际样子来解释完整的HTTP请求报文POST /mes-standard-biz/mesEquipmentStatusRecord/dataUploadForPlc HTTP/1.1 Host: mom.haier-energy.com satoken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ← 请求头 (Request Header) Content-Type: application/json ← 内容头 (Content Header) Content-Length: 123 ← 内容头 (Content Header) {equipmentCode:PLC001,status:Running} ← 请求体 (Request Body)1.satoken- 请求头 (Request Header)req.Headers.TryAddWithoutValidation(satoken, token);特点位置HTTP请求的头部区域作用身份认证- 告诉服务器我是谁生命周期整个请求的元数据不依赖请求体即使没有请求体也可以存在如GET请求实际作用// 服务器端会这样验证 if (request.Headers[satoken] null) return 401 Unauthorized; // 没有token拒绝访问 var user ValidateToken(request.Headers[satoken]); if (user null) return 403 Forbidden; // token无效禁止访问2.application/json- 内容头 (Content Header)req.Content new StringContent(json, Encoding.UTF8, application/json); // 这行代码自动设置了 Content-Type: application/json特点位置HTTP请求的内容头部属于请求体的一部分作用数据格式说明- 告诉服务器我发的是什么格式的数据依赖请求体只有当有请求体时才会存在自动添加StringContent会自动设置实际作用// 服务器端会这样处理 if (request.Content.Headers.ContentType ! application/json) return 415 Unsupported Media Type; // 不支持的媒体类型 // 知道是JSON格式就可以正确解析 var data JsonConvert.DeserializeObject(requestBody);为什么不能混淆❌ 错误做法把Content-Type放在请求头// 这是错误的 req.Headers.TryAddWithoutValidation(Content-Type, application/json); // Content-Type不应该在这里它是内容头不是请求头❌ 错误做法把token放在内容头// 这是错误的 req.Content.Headers.TryAddWithoutValidation(satoken, token); // satoken是认证信息不是内容描述图解区别┌─────────────────────────────────────┐ │ 请求行POST /api/data HTTP/1.1 │ ├─────────────────────────────────────┤ │ 请求头 (Request Headers) │ │ Host: mom.haier-energy.com │ │ satoken: xxxxxx │ ← 身份认证 │ User-Agent: HttpClient │ ├─────────────────────────────────────┤ │ 内容头 (Content Headers) │ │ Content-Type: application/json │ ← 数据格式说明 │ Content-Length: 123 │ ← 数据长度 ├─────────────────────────────────────┤ │ │ │ 请求体 (Request Body) │ │ {key:value} │ ← 实际数据 │ │ └─────────────────────────────────────┘生活中的类比想象你要寄一个快递HTTP元素生活类比作用satoken快递单上的寄件人身份证号证明你是谁是否有权限寄件Content-Type: application/json箱子上的易碎品标签说明箱子里是什么该怎么处理请求体箱子里的实际物品你要传输的真正数据satoken身份证号快递员要验证你是不是合法寄件人application/json易碎品标签告诉搬运工要轻拿轻放两者完全不同不能互换也不能混淆传入头部示例public class MesClient : IDisposable { private readonly HttpClient _http; private readonly string _baseUrl; private readonly bool _enableDetailedLogging; // 可选简单缓存 token private string? _cachedToken; private DateTime _tokenExpire DateTime.MinValue; public MesClient(string baseUrl, bool enableDetailedLogging true) { _baseUrl baseUrl.TrimEnd(/); _enableDetailedLogging enableDetailedLogging; _http new HttpClient { Timeout TimeSpan.FromSeconds(10) }; LogUtil.WriteRunLog($MesClient 初始化: BaseUrl{_baseUrl}, 详细日志{enableDetailedLogging}); } public void Dispose() { _http?.Dispose(); LogUtil.WriteRunLog(MesClient 已释放); } /// summary /// 获取可用 token简单缓存假设 2 小时有效 /// /summary public async Taskstring GetTokenAsync(string username, string tenantCode, CancellationToken ct) { LogUtil.WriteRunLog($ 开始获取Token ); LogUtil.WriteRunLog($用户名: {username}, 租户: {tenantCode}); // 检查缓存 if (!string.IsNullOrEmpty(_cachedToken) DateTime.UtcNow _tokenExpire) { LogUtil.WriteRunLog($使用缓存的Token, 过期时间: {_tokenExpire:yyyy-MM-dd HH:mm:ss}); return _cachedToken!; } LogUtil.WriteRunLog(缓存Token无效或已过期重新获取); try { // 1. 获取授权码 code var codeUrl ${_baseUrl}/platform/oauth/checkCode $?username{Uri.EscapeDataString(username)} $tenantCode{Uri.EscapeDataString(tenantCode)}; LogUtil.WriteRunLog($请求授权码 URL: {codeUrl}); var codeResp await _http.GetAsync(codeUrl, ct); var codeText await codeResp.Content.ReadAsStringAsync(ct); LogUtil.WriteRunLog($授权码响应状态码: {(int)codeResp.StatusCode}); if (_enableDetailedLogging) { LogUtil.WriteRunLog($授权码响应内容: {codeText}); } if (!codeResp.IsSuccessStatusCode) { LogUtil.WriteErrLog($获取授权码失败: HTTP {(int)codeResp.StatusCode}); throw new HttpRequestException($checkCode HTTP {(int)codeResp.StatusCode}: {codeText}); } var codeJson JObject.Parse(codeText); var codeSuccess codeJson.Valuebool?(success) true; var codeResult codeJson.Valuestring(code); LogUtil.WriteRunLog($授权码响应解析 - success: {codeSuccess}, code: {codeResult}); if (codeSuccess ! true || codeResult ! 0) { LogUtil.WriteErrLog($授权码业务失败: {codeText}); throw new Exception($checkCode failed: {codeText}); } var authCode codeJson[result]?.ToString(); if (string.IsNullOrWhiteSpace(authCode)) { LogUtil.WriteErrLog(授权码为空); throw new Exception($checkCode result empty: {codeText}); } LogUtil.WriteRunLog($获取到授权码: {authCode}); // 2. 根据授权码换 token var tokenUrl ${_baseUrl}/platform/oauth/checkToken?code{Uri.EscapeDataString(authCode)}; LogUtil.WriteRunLog($请求Token URL: {tokenUrl}); var tokenResp await _http.GetAsync(tokenUrl, ct); var tokenText await tokenResp.Content.ReadAsStringAsync(ct); LogUtil.WriteRunLog($Token响应状态码: {(int)tokenResp.StatusCode}); if (_enableDetailedLogging) { LogUtil.WriteRunLog($Token响应内容: {tokenText}); } if (!tokenResp.IsSuccessStatusCode) { LogUtil.WriteErrLog($获取Token失败: HTTP {(int)tokenResp.StatusCode}); throw new HttpRequestException($checkToken HTTP {(int)tokenResp.StatusCode}: {tokenText}); } var tokenJson JObject.Parse(tokenText); var tokenSuccess tokenJson.Valuebool?(success) true; var tokenResult tokenJson.Valuestring(code); LogUtil.WriteRunLog($Token响应解析 - success: {tokenSuccess}, code: {tokenResult}); if (tokenSuccess ! true || tokenResult ! 0) { LogUtil.WriteErrLog($Token业务失败: {tokenText}); throw new Exception($checkToken failed: {tokenText}); } var token tokenJson[result]?.ToString(); if (string.IsNullOrWhiteSpace(token)) { LogUtil.WriteErrLog(Token为空); throw new Exception($checkToken result empty: {tokenText}); } // 缓存token _cachedToken token; _tokenExpire DateTime.UtcNow.AddHours(2); LogUtil.WriteRunLog($Token获取成功已缓存过期时间: {_tokenExpire:yyyy-MM-dd HH:mm:ss}); LogUtil.WriteRunLog($Token值: {token.Substring(0, Math.Min(20, token.Length))}...); // 只显示部分Token return token; } catch (Exception ex) { LogUtil.WriteErrLog($获取Token过程异常: {ex.Message}); throw; } } /// summary /// PLC 设备状态变更上传 /// /summary public async Taskbool UploadEquipmentStatusAsync(DeviceStatusResponse dto, CancellationToken ct) { LogUtil.WriteRunLog($ 开始上传设备状态 ); try { // 记录请求数据 if (_enableDetailedLogging) { LogUtil.WriteRunLog($设备状态数据: {JsonConvert.SerializeObject(dto, Formatting.Indented)}); } else { // LogUtil.WriteRunLog($设备编码: {dto.EquipmentCode}, 状态: {dto.Status}, 时间: {dto.UpdateTime}); } // 获取Token var token await GetTokenAsync(TEST01, mom_1001, ct); var url ${_baseUrl}/mes-standard-biz/mesEquipmentStatusRecord/dataUploadForPlc; var json JsonConvert.SerializeObject(dto); LogUtil.WriteRunLog($上传URL: {url}); if (_enableDetailedLogging) { LogUtil.WriteRunLog($请求体JSON: {json}); } // 构建请求 using var req new HttpRequestMessage(HttpMethod.Post, url); req.Headers.TryAddWithoutValidation(satoken, token); req.Content new StringContent(json, Encoding.UTF8, application/json); // 记录请求头 LogUtil.WriteRunLog($请求头: satoken {token.Substring(0, Math.Min(20, token.Length))}...); LogUtil.WriteRunLog($Content-Type: application/json); // 发送请求 LogUtil.WriteRunLog(发送HTTP请求...); var resp await _http.SendAsync(req, ct); LogUtil.WriteRunLog($响应状态码: {(int)resp.StatusCode} {resp.StatusCode}); var text await resp.Content.ReadAsStringAsync(ct); if (_enableDetailedLogging) { LogUtil.WriteRunLog($响应内容: {text}); } else { LogUtil.WriteRunLog($响应长度: {text?.Length ?? 0} 字符); } if (!resp.IsSuccessStatusCode) { LogUtil.WriteErrLog($HTTP请求失败: {(int)resp.StatusCode}); throw new HttpRequestException($Upload HTTP {(int)resp.StatusCode}: {text}); } var obj JObject.Parse(string.IsNullOrWhiteSpace(text) ? {} : text); var success obj.Valuebool?(success) true obj.Valueint?(code) 0; if (success) { LogUtil.WriteRunLog($✅ 设备状态上传成功!); return true; } else { var msg obj.Valuestring(message) ?? text; LogUtil.WriteErrLog($❌ 设备状态上传失败: {msg}); throw new Exception($Upload failed: {msg}); } } catch (Exception ex) { LogUtil.WriteErrLog($上传过程异常: {ex.Message}); throw; } } }使用示例using (var mesClient new MesClient(https://192.168.101.1:6500)) { var result await mesClient.UploadEquipmentStatusAsync(Aging, CancellationToken.None); }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2422433.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!