| 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; | 
| using System.Text; | 
| using System.Threading.Tasks; | 
| using Utility.Tools; | 
| using static System.Net.Mime.MediaTypeNames; | 
| using Utility.Entity; | 
| using Microsoft.AspNetCore.Http; | 
|   | 
| namespace Utility | 
| { | 
|     /// <summary> | 
|     /// 验签 | 
|     /// </summary> | 
|     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] | 
|     public class VerificationAttribute : ActionFilterAttribute | 
|     { | 
|         private string appKey; | 
|         private static readonly double Minutes = SignConfig.Minutes;//时间戳必须5分钟内的,否则不通过 | 
|         public VerificationAttribute() | 
|         { | 
|              | 
|         } | 
|   | 
|         public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) | 
|         { | 
|             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(); | 
|                 return; | 
|             } | 
|   | 
|             // 验证时间戳是否在允许的时间范围内 | 
|             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; | 
|             } | 
|   | 
|             // 读取请求体中的 JSON 参数 | 
|             string jsonParams; | 
|             using (var reader = new System.IO.StreamReader(request.Body, Encoding.UTF8, true, 1024, true)) | 
|             { | 
|                 // 将请求体流位置重置到起始位置 | 
|                 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 = string.Join("&", filteredProperties.OrderBy(p => p.Key).Select(p => p.Key + "=" + p.Value)); | 
|   | 
|             // 计算 MD5 值 | 
|             var computedSignature = Md5Tools.CalcMd5(Encoding.UTF8.GetBytes(signatureBaseString)); | 
|   | 
|             // 验证签名 | 
|             if (computedSignature != signature) | 
|             { | 
|                 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); | 
|                 var currentDateTime = DateTimeOffset.UtcNow; | 
|   | 
|                 // 计算时间差 | 
|                 var timeDifference = currentDateTime - requestDateTime; | 
|   | 
|                 // 比较时间差是否在允许的范围内 | 
|                 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; } | 
|     } | 
|   | 
| } |