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;
|
|
namespace Utility
|
{
|
/// <summary>
|
/// 验签
|
/// </summary>
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
|
public class VerificationAttribute : ActionFilterAttribute
|
{
|
private static readonly string appKey = SignConfig.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 timestamp = request.Headers["Timestamp"].FirstOrDefault();
|
var signature = request.Headers["Signature"].FirstOrDefault();
|
//var timestamp = "1718873584";
|
//var signature = "1718873584";
|
|
if (string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(signature))
|
{
|
context.Result = new UnauthorizedResult();
|
return;
|
}
|
|
// 验证时间戳是否在允许的时间范围内
|
if (!IsTimestampValid(timestamp))
|
{
|
context.Result = new UnauthorizedResult();
|
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;
|
try
|
{
|
jObject = JObject.Parse(jsonParams);
|
}
|
catch (JsonReaderException)
|
{
|
// JSON 格式错误,返回未经授权
|
context.Result = new UnauthorizedResult();
|
return;
|
}
|
// 过滤掉数组类型的属性
|
var filteredProperties = jObject.Properties()
|
.Where(p => p.Value.Type != JTokenType.Array)
|
.ToDictionary(p => p.Name, p => p.Value.ToString());
|
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 AppKey { get; set; }
|
public static double Minutes { get; set; }
|
}
|
|
}
|