Demo
2024-06-20 bca40047b9783d5aadf05d64b128191edb418b09
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
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();
 
            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))
            {
                char[] buffer = new char[500];
                int bytesRead = await reader.ReadAsync(buffer, 0, buffer.Length);
                jsonParams = new string(buffer, 0, bytesRead);
            }
 
            // 构建待签名字符串
            var signatureBaseString = appKey + jsonParams + timestamp;
 
            // 计算 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(logs);
            //    var currentDateTime = DateTimeOffset.UtcNow;
 
            //    // 计算时间差
            //    var timeDifference = currentDateTime - requestDateTime;
 
            //    // 比较时间差是否在允许的范围内
            //    return timeDifference.TotalMinutes <= Minutes;
 
            ////}
            //return false;
 
            try
            {
                var requestDateTime = DateTimeOffset.FromUnixTimeSeconds(long.Parse(timestamp));
                var currentDateTime = DateTimeOffset.UtcNow;
 
                // 计算时间差
                var timeDifference = currentDateTime - requestDateTime;
 
                // 比较时间差是否在允许的范围内
                return timeDifference.TotalMinutes <= Minutes;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
    public class SignConfig
    {
        public static string AppKey { get; set; }
        public static double Minutes { get; set; }
    }
 
}