wxw
2024-08-13 a3236b51b5691b8c47f4ebaf1d885314a4bab3bd
Wms/Utility/Filter/ApiSignatureVerificationAttribute.cs
@@ -1,5 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -7,6 +9,8 @@
using System.Threading.Tasks;
using Utility.Tools;
using static System.Net.Mime.MediaTypeNames;
using Utility.Entity;
using Microsoft.AspNetCore.Http;
namespace Utility
{
@@ -16,11 +20,11 @@
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class VerificationAttribute : ActionFilterAttribute
    {
        private static readonly string appKey = "signature";//后面改成拿配置文件的
        private static readonly double Minutes = 5;//时间戳必须5分钟内的,否则不通过
        private string appKey;
        private static readonly double Minutes = SignConfig.Minutes;//时间戳必须5分钟内的,否则不通过
        public VerificationAttribute()
        {
        }
        public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
@@ -28,9 +32,30 @@
            var request = context.HttpContext.Request;
            // 获取请求中的时间戳和签名
            var system = request.Headers["System"].FirstOrDefault();
            var timestamp = request.Headers["Timestamp"].FirstOrDefault();
            var signature = request.Headers["Signature"].FirstOrDefault();
            //var timestamp = "1718873584";
            //var signature = "1718873584";
            switch (system)
            {
                case "ERP":
                    appKey = SignConfig.ERPAppKey;
                    break;
                case "MES":
                    appKey = SignConfig.MESAppKey;
                    break;
                case "LIMS":
                    appKey = SignConfig.LIMSAppKey;
                    break;
                case "FuMa":
                    appKey = SignConfig.FuMaAppKey;
                    break;
                default:
                    context.Result = new UnauthorizedResult();
                    return;
            }
            if (string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(signature))
            {
                context.Result = new UnauthorizedResult();
@@ -41,6 +66,17 @@
            if (!IsTimestampValid(timestamp))
            {
                context.Result = new UnauthorizedResult();
                var apiResponse = new ApiResponse<object>(
                    401,
                    "error",
                    "时间失效"
                );
                var json = JsonConvert.SerializeObject(apiResponse);
                context.HttpContext.Response.ContentType = "application/json";
                context.HttpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(json);
                await context.HttpContext.Response.WriteAsync(json);
                await base.OnActionExecutionAsync(context, next);
                return;
            }
@@ -48,13 +84,36 @@
            string jsonParams;
            using (var reader = new System.IO.StreamReader(request.Body, Encoding.UTF8, true, 1024, true))
            {
                char[] buffer = new char[500];
                int bytesRead = await reader.ReadAsync(buffer, 0, buffer.Length);
                jsonParams = new string(buffer, 0, bytesRead);
                // 将请求体流位置重置到起始位置
                request.Body.Seek(0, System.IO.SeekOrigin.Begin);
                jsonParams = await reader.ReadToEndAsync();
            }
            // 反序列化 JSON 参数为 JObject
            JObject jObject = null;
            Dictionary<string, string> filteredProperties = new Dictionary<string, string>();
            if (jsonParams != null)
            {
                try
                {
                    jObject = JObject.Parse(jsonParams);
                    // 过滤掉数组类型的属性
                    filteredProperties = jObject.Properties()
                        .Where(p => p.Value.Type != JTokenType.Array)
                        .ToDictionary(p => p.Name, p => p.Value.ToString());
                }
                catch (JsonReaderException)
                {
                    // JSON 格式错误,返回未经授权
                    context.Result = new UnauthorizedResult();
                    return;
                }
            }
            filteredProperties.Add("timestamp", timestamp);
            filteredProperties.Add("appKey", appKey);
            // 构建待签名字符串
            var signatureBaseString = appKey + jsonParams + timestamp;
            var signatureBaseString = string.Join("&", filteredProperties.OrderBy(p => p.Key).Select(p => p.Key + "=" + p.Value));
            // 计算 MD5 值
            var computedSignature = Md5Tools.CalcMd5(Encoding.UTF8.GetBytes(signatureBaseString));
@@ -65,12 +124,13 @@
                context.Result = new UnauthorizedResult();
                return;
            }
            await base.OnActionExecutionAsync(context, next);
        }
        private bool IsTimestampValid(string timestamp)
        {
            //var logs = long.Parse(timestamp);
            //var logs2 = int.Parse(timestamp);
            if (long.TryParse(timestamp, out var timestampSeconds))
            {
                var requestDateTime = DateTimeOffset.FromUnixTimeSeconds(timestampSeconds);
@@ -80,10 +140,20 @@
                var timeDifference = currentDateTime - requestDateTime;
                // 比较时间差是否在允许的范围内
                return timeDifference.TotalMinutes <= 5;
            }
                return timeDifference.TotalMinutes <= Minutes;
            }
            return false;
        }
    }
}
    public class SignConfig
    {
        public static string ERPAppKey { get; set; }
        public static string MESAppKey { get; set; }
        public static string LIMSAppKey { get; set; }
        public static string FuMaAppKey { get; set; }
        public static double Minutes { get; set; }
    }
}