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 {
|
/// <summary>
|
/// 设备信息上报(HostToAGV上报、杭奥堆垛机、国自AGV)
|
/// </summary>
|
[RoutePrefix("agv")]
|
public class AgvController : ApiController
|
{
|
/// <summary>
|
/// NDC HostToAGV 任务状态回报
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
[HttpPost]
|
[Route("AGVCallbackState")]
|
public ReturnResult AGVCallbackState(AgvTaskState model){
|
LogHelper.InfoHostToAGV("NDC任务状态回报", model);
|
return WCSCore.OperateAgvTaskStatus(model);
|
}
|
|
/// <summary>
|
/// AGV 与产线进行安全交互
|
/// </summary>
|
/// <param name="model"></param>
|
/// <returns></returns>
|
[HttpPost]
|
[Route("SafetyInteraction")]
|
public ReturnResult SafetyInteraction(SafetyInteractionInfo model) {
|
LogHelper.InfoHostToAGV("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; }
|
}
|
}
|