| | |
| | | [HttpPost] |
| | | [Route("AGVCallbackState")] |
| | | public ReturnResult AGVCallbackState(AgvTaskState model){ |
| | | LogHelper.Info("NDC HostToAGV 任务状态回报:" + JsonConvert.SerializeObject(model), "HosttoagvTask"); |
| | | LogHelper.InfoHostToAGV("AGVCallbackState:NDC任务状态回报", model); |
| | | return WCSCore.OperateAgvTaskStatus(model); |
| | | } |
| | | |
| | |
| | | [HttpPost] |
| | | [Route("SafetyInteraction")] |
| | | public ReturnResult SafetyInteraction(SafetyInteractionInfo model) { |
| | | LogHelper.Info("AGV与产线进行安全交互:" + JsonConvert.SerializeObject(model), "HosttoagvTask"); |
| | | LogHelper.InfoHostToAGV("SafetyInteraction:AGV与产线进行安全交互", model); |
| | | return WCSCore.SafetyInteraction(model); |
| | | } |
| | | |
| | | |
| | | |
| | | // 备用:Request 请求授权 --------------------------------------------- |
| | | |
| | | // 模拟存储的AppKey和AppSecret(实际应存储在数据库或配置中) |
| | | private static readonly Dictionary<string, string> AppSecrets = new Dictionary<string, string> { |
| | | { "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; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 构造一个成功结果的ResponseMessage |
| | | /// </summary> |
| | | /// <example><code><![CDATA[ |
| | | /// var res = ApiHelper.OperateAgvTaskStatus(model); |
| | | /// return CreateSuccessResponse(res); |
| | | /// ]]></code></example> |
| | | /// <param name="code"></param> |
| | | /// <param name="data"></param> |
| | | /// <returns></returns> |
| | | private IHttpActionResult CreateSuccessResponse(HttpStatusCode code, object data) { |
| | | return ResponseMessage(new HttpResponseMessage(code) { |
| | | Headers = { }, |
| | | Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json") |
| | | }); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 构造一个失败结果的ResponseMessage |
| | | /// </summary> |
| | | /// <example><code><![CDATA[ |
| | | /// var headers = Request.Headers; |
| | | /// var checkRes = CheckHeaders(headers); |
| | | /// if (!checkRes.isSuccess) { |
| | | /// return CreateErrorResponse(checkRes.code, checkRes.message); |
| | | /// } |
| | | /// ]]></code></example> |
| | | /// <param name="code"></param> |
| | | /// <param name="message"></param> |
| | | /// <returns></returns> |
| | | 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; } |
| | | } |
| | | } |