using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Web.Http; using HH.WCS.Mobox3.DSZSH.core; using Newtonsoft.Json; using static HH.WCS.Mobox3.DSZSH.api.ApiModel; using static HH.WCS.Mobox3.DSZSH.dispatch.NDC; namespace HH.WCS.Mobox3.DSZSH.api { /// /// 设备信息上报(HostToAGV上报、杭奥堆垛机、国自AGV) /// [RoutePrefix("agv")] public class AgvController : ApiController { /// /// NDC HostToAGV 任务状态回报 /// /// /// [HttpPost] [Route("AGVCallbackState")] public ReturnResult AGVCallbackState(AgvTaskState model){ LogHelper.InfoHostToAGV("NDC任务状态回报", model); return WCSCore.OperateAgvTaskStatus(model); } /// /// AGV 与产线进行安全交互 /// /// /// [HttpPost] [Route("SafetyInteraction")] public ReturnResult SafetyInteraction(SafetyInteractionInfo model) { LogHelper.InfoHostToAGV("AGV与产线进行安全交互", model); return WCSCore.SafetyInteraction(model); } // 备用:Request 请求授权 --------------------------------------------- // 模拟存储的AppKey和AppSecret(实际应存储在数据库或配置中) private static readonly Dictionary AppSecrets = new Dictionary { { "testAppKey", "7a8f9b3d2e1c6a5b4c8d7e6f" } }; // 允许的时间差(秒),用于验证时间戳 private const int AllowedTimeDiff = 300; // 5分钟 private CheckHeadersResult CheckHeaders(System.Net.Http.Headers.HttpRequestHeaders headers) { // 必须字段验证 if (!headers.Contains("AppKey") || !headers.Contains("ReqVerify") || !headers.Contains("ReqTime")) { return CreateCheckHeadersResult(false, HttpStatusCode.BadRequest, "缺少必要请求头参数"); } var headerModel = new SecureRequest { AppKey = headers.GetValues("AppKey").First(), ReqVerify = headers.GetValues("ReqVerify").First(), ReqTime = long.Parse(headers.GetValues("ReqTime").First()), }; // 验证Header var validationResult = ValidateHeaders(headerModel); if (validationResult != null) { return validationResult; } return CreateCheckHeadersResult(true); } private CheckHeadersResult ValidateHeaders(SecureRequest request) { // 实现所有Header验证逻辑 // 验证AppKey是否存在 if (!AppSecrets.TryGetValue(request.AppKey, out var appSecret)) { return CreateCheckHeadersResult(false, HttpStatusCode.Unauthorized, "无效的AppKey"); } // 验证时间戳是否在允许范围内 var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); if (Math.Abs(currentTime - request.ReqTime) > AllowedTimeDiff) { return CreateCheckHeadersResult(false, HttpStatusCode.Unauthorized, "请求已过期"); } // 计算验证串 var expectedVerify = CalculateRequestVerify(request.AppKey, appSecret, request.ReqTime); // 验证请求签名 if (!string.Equals(expectedVerify, request.ReqVerify, StringComparison.OrdinalIgnoreCase)) { return CreateCheckHeadersResult(false, HttpStatusCode.Unauthorized, "验证失败"); } return null; } /// /// 构造一个成功结果的ResponseMessage /// /// /// /// /// private IHttpActionResult CreateSuccessResponse(HttpStatusCode code, object data) { return ResponseMessage(new HttpResponseMessage(code) { Headers = { }, Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json") }); } /// /// 构造一个失败结果的ResponseMessage /// /// /// /// /// private IHttpActionResult CreateErrorResponse(HttpStatusCode code, string message) { return ResponseMessage(new HttpResponseMessage(code) { Headers = { }, Content = new StringContent(message) }); } private CheckHeadersResult CreateCheckHeadersResult(bool isSuccess, HttpStatusCode code = HttpStatusCode.OK, string message = "") { return new CheckHeadersResult { code = code, message = message, isSuccess = isSuccess }; } // 计算请求验证串 private string CalculateRequestVerify(string appKey, string appSecret, long reqTime) { using (var md5 = MD5.Create()) { var input = $"{appKey}{appSecret}{reqTime}"; var inputBytes = Encoding.UTF8.GetBytes(input); var hashBytes = md5.ComputeHash(inputBytes); // 将字节数组转换为十六进制字符串 var sb = new StringBuilder(); foreach (var b in hashBytes) { sb.Append(b.ToString("x2")); } return sb.ToString(); } } } // 请求模型 public class SecureRequest { public string AppKey { get; set; } public long ReqTime { get; set; } public string ReqVerify { get; set; } } public class CheckHeadersResult { public bool isSuccess { get; set; } public HttpStatusCode code { get; set; } public string message { get; set; } } }