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.Info("NDC HostToAGV 任务状态回报:" + JsonConvert.SerializeObject(model), "HosttoagvTask");
return WCSCore.OperateAgvTaskStatus(model);
}
///
/// AGV 与产线进行安全交互
///
///
///
[HttpPost]
[Route("SafetyInteraction")]
public ReturnResult SafetyInteraction(SafetyInteractionInfo model) {
LogHelper.Info("AGV与产线进行安全交互:" + JsonConvert.SerializeObject(model), "HosttoagvTask");
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; }
}
}