using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using QRCodeService.Application.Queries; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text.Json; using System.Text.Json.Serialization; using QRCodeService.Extensions; namespace QRCodeService.Infrastructure.Middlewares { /// /// 报文签名验证中间件 /// public class CheckSignMiddleware { readonly RequestDelegate next; public CheckSignMiddleware(RequestDelegate next) { this.next = next; } public async Task Invoke(HttpContext context, IAppQueries appQueries) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var endpoint = context.GetEndpoint(); if (endpoint != null) { var attribute = endpoint.Metadata.GetMetadata(); if (attribute != null) { context.Request.EnableBuffering(); var requestReader = new StreamReader(context.Request.Body); var requestContent = await requestReader.ReadToEndAsync(); var param = JsonSerializer.Deserialize(requestContent,attribute.ModelType); var props = attribute.ModelType.GetProperties(); var appid = (int)props.Single(p=>p.Name=="AppId").GetValue(param); var time = props.Single(p => p.Name == "Time").GetValue(param) as string; var sign = props.Single(p => p.Name == "Sign").GetValue(param) as string; var timeDate = time.ToDate("yyyyMMddHHmmss"); if (timeDate == null||Math.Abs((timeDate.Value - DateTime.Now).TotalSeconds) > 60)//时间不同步 { context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.BodyWriter.WriteAsync(Encoding.UTF8.GetBytes("check sign failed")); return; } var app = await appQueries.GetAppAsync(appid); if (app == null) { context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.BodyWriter.WriteAsync(Encoding.UTF8.GetBytes("check sign failed")); return; } var appKey = app.Appkey; var signStr = string.Join(null, props.Where(p => p.Name != "Sign").OrderBy(p => p.Name).Select(p => p.GetValue(param).ToString())); var checkSign = BitConverter.ToString( (signStr + appKey).ToMD5()).Replace("-",""); if(checkSign.ToLower() != sign.ToLower()) { context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.BodyWriter.WriteAsync(Encoding.UTF8.GetBytes("check sign failed")); return; } context.Request.Body.Position = 0; } } await next(context); } } }