diff --git a/QRCodeService/Application/Queries/AppQueries.cs b/QRCodeService/Application/Queries/AppQueries.cs new file mode 100644 index 0000000..1db9f87 --- /dev/null +++ b/QRCodeService/Application/Queries/AppQueries.cs @@ -0,0 +1,32 @@ +using Dapper; +using Microsoft.Extensions.Configuration; +using MySqlConnector; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QRCodeService.Application.Queries +{ + public class AppQueries : IAppQueries + { + readonly string _connectionString; + + public AppQueries(IConfiguration configuration) + { + _connectionString = configuration.GetConnectionString("default"); + } + + public async Task GetAppAsync(int id) + { + using (var connection = new MySqlConnection(_connectionString)) + { + connection.Open(); + var app = await connection.QueryAsync( + @"SELECT Id,AppKey,Remarks FROM App WHERE Id = @id", new { id }); + return app.SingleOrDefault(); + } + } + } +} diff --git a/QRCodeService/Application/Queries/AppViewModel.cs b/QRCodeService/Application/Queries/AppViewModel.cs new file mode 100644 index 0000000..5d87e54 --- /dev/null +++ b/QRCodeService/Application/Queries/AppViewModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QRCodeService.Application.Queries +{ + public class App + { + public int Id { get; set; } + public string Appkey { get; set; } + public string Remarks { get; set; } + } +} diff --git a/QRCodeService/Application/Queries/GetLinkQueryHandler.cs b/QRCodeService/Application/Queries/IAppQueries.cs similarity index 71% rename from QRCodeService/Application/Queries/GetLinkQueryHandler.cs rename to QRCodeService/Application/Queries/IAppQueries.cs index b8a5469..ca4d274 100644 --- a/QRCodeService/Application/Queries/GetLinkQueryHandler.cs +++ b/QRCodeService/Application/Queries/IAppQueries.cs @@ -6,8 +6,8 @@ using System.Threading.Tasks; namespace QRCodeService.Application.Queries { - public class GetLinkQueryHandler + public interface IAppQueries { - + Task GetAppAsync(int id); } } diff --git a/QRCodeService/Application/Queries/LinkQueries.cs b/QRCodeService/Application/Queries/LinkQueries.cs index 2c99f0e..cbec2be 100644 --- a/QRCodeService/Application/Queries/LinkQueries.cs +++ b/QRCodeService/Application/Queries/LinkQueries.cs @@ -26,7 +26,7 @@ namespace QRCodeService.Application.Queries connection.Open(); var link = await connection.QueryAsync( @"SELECT ShortCode,FullUrl FROM Link WHERE ShortCode = @shortCode",new {shortCode }); - return link.Single(); + return link.SingleOrDefault(); } } } diff --git a/QRCodeService/Controllers/Api/LinkController.cs b/QRCodeService/Controllers/Api/LinkController.cs index 0daf526..ca537b7 100644 --- a/QRCodeService/Controllers/Api/LinkController.cs +++ b/QRCodeService/Controllers/Api/LinkController.cs @@ -18,12 +18,14 @@ namespace QRCodeService.Controllers.Api public class LinkController:ControllerBase { readonly IMediator mediator; - readonly ILinkQueries queries; + readonly ILinkQueries linkQueries; + readonly IAppQueries appQueries; - public LinkController(IMediator mediator, ILinkQueries queries) + public LinkController(IMediator mediator, ILinkQueries queries, IAppQueries appQueries) { this.mediator = mediator; - this.queries = queries; + this.linkQueries = queries; + this.appQueries = appQueries; } [HttpGet] @@ -34,6 +36,15 @@ namespace QRCodeService.Controllers.Api [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/Extensions/StringExtension.cs b/QRCodeService/Extensions/StringExtension.cs index bc24862..aa928d4 100644 --- a/QRCodeService/Extensions/StringExtension.cs +++ b/QRCodeService/Extensions/StringExtension.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Security.Cryptography; using System.Text; @@ -17,5 +18,30 @@ namespace QRCodeService.Extensions return result; } } + public static DateTime? ToDate(this string dateTimeStr, string[] dateFmt) + { + // example: var dt = "2011-03-21 13:26".toDate(new string[]{"yyyy-MM-dd HH:mm", + // "M/d/yyyy h:mm:ss tt"}); + const DateTimeStyles style = DateTimeStyles.AllowWhiteSpaces; + if (dateFmt == null) + { + var dateInfo = System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat; + dateFmt = dateInfo.GetAllDateTimePatterns(); + } + DateTime? result = null; + DateTime dt; + if (DateTime.TryParseExact(dateTimeStr, dateFmt, + CultureInfo.InvariantCulture, style, out dt)) result = dt; + return result; + } + + public static DateTime? ToDate(this string dateTimeStr, string dateFmt = null) + { + // example: var dt="2011-03-21 13:26".toDate("yyyy-MM-dd HH:mm"); + // or simply var dt="2011-03-21 13:26".toDate(); + // call overloaded function with string array param + string[] dateFmtArr = dateFmt == null ? null : new string[] { dateFmt }; + return ToDate(dateTimeStr, dateFmtArr); + } } } diff --git a/QRCodeService/Models/CheckSignModel.cs b/QRCodeService/Models/CheckSignModel.cs new file mode 100644 index 0000000..2bad90a --- /dev/null +++ b/QRCodeService/Models/CheckSignModel.cs @@ -0,0 +1,43 @@ +using QRCodeService.Application.Queries; +using QRCodeService.Extensions; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QRCodeService.Models +{ + public abstract class CheckSignModel + { + 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/Models/CreateLinkModel.cs b/QRCodeService/Models/CreateLinkModel.cs index f823cc0..caba500 100644 --- a/QRCodeService/Models/CreateLinkModel.cs +++ b/QRCodeService/Models/CreateLinkModel.cs @@ -1,4 +1,5 @@ -using System; +using QRCodeService.Application.Queries; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,9 +7,8 @@ using System.Threading.Tasks; namespace QRCodeService.Models { - public class CreateLinkModel + public class CreateLinkModel: CheckSignModel { public string SuffixUrl { get; set; } - public string Time { get; set; } } } diff --git a/QRCodeService/Models/GenInputModel.cs b/QRCodeService/Models/GenInputModel.cs deleted file mode 100644 index e7975dd..0000000 --- a/QRCodeService/Models/GenInputModel.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace QRCodeService.Models -{ - public class GenInputModel - { - public int AppId { get; set; } - public string Time { get; set; } - public string SuffixUrl { get; set; } - public string Sign { get; set; } - } -} diff --git a/QRCodeService/Startup.cs b/QRCodeService/Startup.cs index e793c25..3e35c0c 100644 --- a/QRCodeService/Startup.cs +++ b/QRCodeService/Startup.cs @@ -71,8 +71,10 @@ namespace QRCodeService //Repository services.AddScoped(); services.AddScoped(); + //Queries services.AddScoped(); - + services.AddScoped(); + } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/README.md b/README.md index 1d0e864..8381935 100644 --- a/README.md +++ b/README.md @@ -1 +1,6 @@ -# 施工图审查系统二维码短链生成服务 \ No newline at end of file +# 施工图审查系统二维码短链生成服务 +## 开发环境搭建 +1. 安装vs 2019 +2. 安装.net 5 SDK +3. 安装docker desktop +## 启动项目 \ No newline at end of file