| | |
| | | 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.Threading.Tasks; |
| | | using Utility.Tools; |
| | | using static System.Net.Mime.MediaTypeNames; |
| | | using Utility.Entity; |
| | | using Microsoft.AspNetCore.Http; |
| | | |
| | | namespace Utility |
| | | { |
| | |
| | | [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) |
| | |
| | | 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(); |
| | |
| | | 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; |
| | | } |
| | | |
| | |
| | | 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)); |
| | |
| | | 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 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; } |
| | | } |
| | | |
| | | } |