From 92a53ebb95ff8af7eeb29578728e097f09941949 Mon Sep 17 00:00:00 2001
From: yusijie <ysj@hz-kingdee.com>
Date: 星期二, 28 四月 2026 15:35:49 +0800
Subject: [PATCH] Merge branch 'master' of http://101.37.171.70:10101/r/MES-WEB-API

---
 WebAPI/Service/SignatureVerifyAttribute.cs |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/WebAPI/Service/SignatureVerifyAttribute.cs b/WebAPI/Service/SignatureVerifyAttribute.cs
new file mode 100644
index 0000000..8f24798
--- /dev/null
+++ b/WebAPI/Service/SignatureVerifyAttribute.cs
@@ -0,0 +1,113 @@
+锘縰sing System;
+using System.Linq;
+using System.Net.Http;
+using System.Security.Cryptography;
+using System.Text;
+using System.Web.Http;
+using System.Web.Http.Controllers;
+using System.Web.Http.Filters;
+using WebAPI;
+using WebAPI.Service;
+
+namespace project.Filter
+{
+    public class SignatureVerifyAttribute : AuthorizationFilterAttribute
+    {
+        private const string SecretKey = "MES_2026_SecretKey_XYZ!@#";
+
+        public override async System.Threading.Tasks.Task OnAuthorizationAsync(
+            HttpActionContext actionContext,
+            System.Threading.CancellationToken cancellationToken)
+        {
+            var hasAttr = actionContext.ActionDescriptor.GetCustomAttributes<RequireSignatureAttribute>(true).Any()
+                       || actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<RequireSignatureAttribute>(true).Any();
+
+            if (!hasAttr)
+            {
+                return; 
+            }
+
+            var headers = actionContext.Request.Headers;
+            string timestamp = null, nonce = null, clientSign = null;
+
+            if (headers.Contains("X-Timestamp"))
+                timestamp = headers.GetValues("X-Timestamp").FirstOrDefault();
+            if (headers.Contains("X-Nonce"))
+                nonce = headers.GetValues("X-Nonce").FirstOrDefault();
+            if (headers.Contains("X-Sign"))
+                clientSign = headers.GetValues("X-Sign").FirstOrDefault();
+
+            if (string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(nonce) || string.IsNullOrEmpty(clientSign))
+            {
+                actionContext.Response = actionContext.Request.CreateResponse(System.Net.HttpStatusCode.BadRequest,
+                    new { success = false, msg = "缂哄皯绛惧悕鍙傛暟锛圶-Timestamp/X-Nonce/X-Sign锛�" });
+                return;
+            }
+
+
+            double ts;
+            if (!double.TryParse(timestamp, out ts))
+            {
+                actionContext.Response = actionContext.Request.CreateResponse(System.Net.HttpStatusCode.BadRequest,
+                    new { success = false, msg = "鏃堕棿鎴虫牸寮忛敊璇�" });
+                return;
+            }
+            var currentTs = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
+            var diff = Math.Abs(currentTs - ts);
+            if (diff > 300) // 300绉� = 5鍒嗛挓
+            {
+                actionContext.Response = actionContext.Request.CreateResponse(System.Net.HttpStatusCode.BadRequest,
+                    new { success = false, msg = "璇锋眰宸茶繃鏈�" });
+                return;
+            }
+
+            string rawData = "";
+
+            if (actionContext.Request.Method == HttpMethod.Get)
+            {
+                var query = actionContext.Request.RequestUri.Query;
+                if (!string.IsNullOrEmpty(query) && query.StartsWith("?"))
+                {
+                    rawData = query.Substring(1); 
+
+                }
+            }
+            else
+            {
+                var bodyBytes = await actionContext.Request.Content.ReadAsByteArrayAsync();
+                rawData = Encoding.UTF8.GetString(bodyBytes);
+
+                actionContext.Request.Content = new ByteArrayContent(bodyBytes);
+                if (actionContext.Request.Content.Headers.ContentType != null)
+                {
+                    actionContext.Request.Content.Headers.ContentType =
+                        new System.Net.Http.Headers.MediaTypeHeaderValue(
+                            actionContext.Request.Content.Headers.ContentType.MediaType);
+                }
+            }
+            rawData = rawData.Replace("'", "%27");
+            var signStr = rawData + "&timestamp=" + timestamp + "&nonce=" + nonce + "&key=" + SecretKey;
+            var serverSign = ComputeHmacSha256(signStr, SecretKey);
+
+            
+            if (serverSign != clientSign.ToUpper())
+            {
+                actionContext.Response = actionContext.Request.CreateResponse(System.Net.HttpStatusCode.Unauthorized,
+                    new { success = false, msg = "绛惧悕楠岃瘉澶辫触" });
+                return;
+            }
+        }
+
+        private string ComputeHmacSha256(string data, string key)
+        {
+            var keyBytes = Encoding.UTF8.GetBytes(key);
+            var dataBytes = Encoding.UTF8.GetBytes(data);
+
+            using (var hmac = new HMACSHA256(keyBytes))
+            {
+                var hashBytes = hmac.ComputeHash(dataBytes);
+                return BitConverter.ToString(hashBytes).Replace("-", "").ToUpper();
+            }
+        }
+    }
+}
\ No newline at end of file

--
Gitblit v1.9.1