From d6617f47c01dc6d02ce7b5f4dc6fdc6dc10f1d57 Mon Sep 17 00:00:00 2001 From: zhangqi <2794379662@qq.com> Date: Fri, 26 Feb 2021 16:40:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E7=AD=BE=E5=90=8D=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E8=87=AA=E5=AE=9A=E4=B9=89=E4=B8=AD=E9=97=B4=E4=BB=B6?= =?UTF-8?q?=20,=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Api/LinkController.cs | 31 ++++---- QRCodeService/Controllers/ImageController.cs | 12 +-- .../Extensions/ControllerBaseExtension.cs | 13 ++++ ...eExtensions.cs => GenericTypeExtension.cs} | 2 +- .../Middlewares/CheckSignAttribute.cs | 18 +++++ .../Middlewares/CheckSignMiddleware.cs | 78 +++++++++++++++++++ QRCodeService/Models/CheckSignModel.cs | 25 ------ QRCodeService/Startup.cs | 3 +- 8 files changed, 128 insertions(+), 54 deletions(-) create mode 100644 QRCodeService/Extensions/ControllerBaseExtension.cs rename QRCodeService/Extensions/{GenericTypeExtensions.cs => GenericTypeExtension.cs} (94%) create mode 100644 QRCodeService/Infrastructure/Middlewares/CheckSignAttribute.cs create mode 100644 QRCodeService/Infrastructure/Middlewares/CheckSignMiddleware.cs diff --git a/QRCodeService/Controllers/Api/LinkController.cs b/QRCodeService/Controllers/Api/LinkController.cs index ca537b7..5d21f26 100644 --- a/QRCodeService/Controllers/Api/LinkController.cs +++ b/QRCodeService/Controllers/Api/LinkController.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using MediatR; using QRCodeService.Application.Queries; using QRCodeService.Application.Commands; +using QRCodeService.Infrastructure.Middlewares; namespace QRCodeService.Controllers.Api { @@ -19,32 +20,28 @@ namespace QRCodeService.Controllers.Api { readonly IMediator mediator; readonly ILinkQueries linkQueries; - readonly IAppQueries appQueries; - public LinkController(IMediator mediator, ILinkQueries queries, IAppQueries appQueries) + public LinkController(IMediator mediator, ILinkQueries queries) { this.mediator = mediator; this.linkQueries = queries; - this.appQueries = appQueries; + } + [Route("{shortCode}")] + [HttpGet] + public async Task Get(string shortCode) + { + var link = await linkQueries.GetLinkAsync(shortCode); + if (link == null) + { + return NotFound(); + } + return Ok(link); } - [HttpGet] - public IActionResult Get() - { - return Ok(); - } + [CheckSign(typeof(CreateLinkModel))] [HttpPost] public async Task Create(CreateLinkModel input) { - var app = await appQueries.GetAppAsync(input.AppId); - if (app == null) - { - return BadRequest(); - } - if (! await input.CheckValidAsync(app.Appkey)) - { - return BadRequest(); - } var command = new CreateLinkCommand(input.SuffixUrl,1); var link = await mediator.Send(command); if (link==null) diff --git a/QRCodeService/Controllers/ImageController.cs b/QRCodeService/Controllers/ImageController.cs index 4920173..b78cf83 100644 --- a/QRCodeService/Controllers/ImageController.cs +++ b/QRCodeService/Controllers/ImageController.cs @@ -9,6 +9,7 @@ using System.IO; using QRCodeService.Application.Queries; using QRCodeService.Models; using QRCodeService.Options; +using QRCodeService.Infrastructure.Middlewares; namespace QRCodeService.Controllers { @@ -25,20 +26,11 @@ namespace QRCodeService.Controllers this.appQueries = appQueries; this.option = option; } - + [CheckSign(typeof(GetQRCodeModel))] [Route("qrcode")] [HttpPost] public async Task GetImage(GetQRCodeModel input) { - var app = await appQueries.GetAppAsync(input.AppId); - if (app == null) - { - return BadRequest(); - } - if (!await input.CheckValidAsync(app.Appkey)) - { - return BadRequest(); - } var link = await linkQueries.GetLinkAsync(input.ShortCode); if (link.AppId != input.AppId) { diff --git a/QRCodeService/Extensions/ControllerBaseExtension.cs b/QRCodeService/Extensions/ControllerBaseExtension.cs new file mode 100644 index 0000000..5ce0784 --- /dev/null +++ b/QRCodeService/Extensions/ControllerBaseExtension.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QRCodeService.Extensions +{ + public static class ControllerBaseExtension + { + + } +} diff --git a/QRCodeService/Extensions/GenericTypeExtensions.cs b/QRCodeService/Extensions/GenericTypeExtension.cs similarity index 94% rename from QRCodeService/Extensions/GenericTypeExtensions.cs rename to QRCodeService/Extensions/GenericTypeExtension.cs index c748e57..c54293c 100644 --- a/QRCodeService/Extensions/GenericTypeExtensions.cs +++ b/QRCodeService/Extensions/GenericTypeExtension.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace QRCodeService.Extensions { - public static class GenericTypeExtensions + public static class GenericTypeExtension { public static string GetGenericTypeName(this Type type) { diff --git a/QRCodeService/Infrastructure/Middlewares/CheckSignAttribute.cs b/QRCodeService/Infrastructure/Middlewares/CheckSignAttribute.cs new file mode 100644 index 0000000..11f01f3 --- /dev/null +++ b/QRCodeService/Infrastructure/Middlewares/CheckSignAttribute.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QRCodeService.Infrastructure.Middlewares +{ + public class CheckSignAttribute:Attribute + { + public Type ModelType { get; set; } + + public CheckSignAttribute(Type type) + { + ModelType = type; + } + } +} diff --git a/QRCodeService/Infrastructure/Middlewares/CheckSignMiddleware.cs b/QRCodeService/Infrastructure/Middlewares/CheckSignMiddleware.cs new file mode 100644 index 0000000..6b5feef --- /dev/null +++ b/QRCodeService/Infrastructure/Middlewares/CheckSignMiddleware.cs @@ -0,0 +1,78 @@ +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); + } + } +} diff --git a/QRCodeService/Models/CheckSignModel.cs b/QRCodeService/Models/CheckSignModel.cs index 2bad90a..8d0e8ed 100644 --- a/QRCodeService/Models/CheckSignModel.cs +++ b/QRCodeService/Models/CheckSignModel.cs @@ -14,30 +14,5 @@ namespace QRCodeService.Models public int AppId { get; set; } public string Time { get; set; } public string Sign { get; set; } - public async Task CheckSignAsync(string appkey) - { - //除Sign字段以外按key名排序 - var props = this.GetType().GetProperties(); - var signStr = string.Join(null,props.Where(p=>p.Name!="Sign").OrderBy(p => p.Name).Select(p=>p.GetValue(this).ToString())); - var sign = Convert.ToBase64String((signStr + appkey).ToMD5()); - return sign == Sign; - } - public bool CheckTime() - { - var timeDate = Time.ToDate("yyyyMMddhhmmss"); - if (timeDate == null) - { - return false; - } - if (Math.Abs((timeDate.Value - DateTime.Now).TotalSeconds) > 60) - { - return false; - } - return true; - } - public async Task CheckValidAsync(string appkey) - { - return CheckTime() && await CheckSignAsync(appkey); - } } } diff --git a/QRCodeService/Startup.cs b/QRCodeService/Startup.cs index fadb66f..99ac022 100644 --- a/QRCodeService/Startup.cs +++ b/QRCodeService/Startup.cs @@ -22,6 +22,7 @@ using QRCodeService.Application.Behaviors; using QRCodeService.Application.Commands; using QRCodeService.Application.Queries; using QRCodeService.Application.Validations; +using QRCodeService.Infrastructure.Middlewares; using QRCodeService.Options; using System; using System.Collections.Generic; @@ -104,7 +105,7 @@ namespace QRCodeService app.UseRouting(); app.UseAuthorization(); - + app.UseMiddleware(); app.UseEndpoints(endpoints => { endpoints.MapControllers();