update:请求加密&防篡改
This commit is contained in:
32
QRCodeService/Application/Queries/AppQueries.cs
Normal file
32
QRCodeService/Application/Queries/AppQueries.cs
Normal file
@@ -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<App> GetAppAsync(int id)
|
||||||
|
{
|
||||||
|
using (var connection = new MySqlConnection(_connectionString))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
var app = await connection.QueryAsync<App>(
|
||||||
|
@"SELECT Id,AppKey,Remarks FROM App WHERE Id = @id", new { id });
|
||||||
|
return app.SingleOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
QRCodeService/Application/Queries/AppViewModel.cs
Normal file
15
QRCodeService/Application/Queries/AppViewModel.cs
Normal file
@@ -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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,8 +6,8 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace QRCodeService.Application.Queries
|
namespace QRCodeService.Application.Queries
|
||||||
{
|
{
|
||||||
public class GetLinkQueryHandler
|
public interface IAppQueries
|
||||||
{
|
{
|
||||||
|
Task<App> GetAppAsync(int id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ namespace QRCodeService.Application.Queries
|
|||||||
connection.Open();
|
connection.Open();
|
||||||
var link = await connection.QueryAsync<Link>(
|
var link = await connection.QueryAsync<Link>(
|
||||||
@"SELECT ShortCode,FullUrl FROM Link WHERE ShortCode = @shortCode",new {shortCode });
|
@"SELECT ShortCode,FullUrl FROM Link WHERE ShortCode = @shortCode",new {shortCode });
|
||||||
return link.Single();
|
return link.SingleOrDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,14 @@ namespace QRCodeService.Controllers.Api
|
|||||||
public class LinkController:ControllerBase
|
public class LinkController:ControllerBase
|
||||||
{
|
{
|
||||||
readonly IMediator mediator;
|
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.mediator = mediator;
|
||||||
this.queries = queries;
|
this.linkQueries = queries;
|
||||||
|
this.appQueries = appQueries;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
@@ -34,6 +36,15 @@ namespace QRCodeService.Controllers.Api
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> Create(CreateLinkModel input)
|
public async Task<IActionResult> 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 command = new CreateLinkCommand(input.SuffixUrl,1);
|
||||||
var link = await mediator.Send(command);
|
var link = await mediator.Send(command);
|
||||||
if (link==null)
|
if (link==null)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -17,5 +18,30 @@ namespace QRCodeService.Extensions
|
|||||||
return result;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
43
QRCodeService/Models/CheckSignModel.cs
Normal file
43
QRCodeService/Models/CheckSignModel.cs
Normal file
@@ -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<bool> 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<bool> CheckValidAsync(string appkey)
|
||||||
|
{
|
||||||
|
return CheckTime() && await CheckSignAsync(appkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using QRCodeService.Application.Queries;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -6,9 +7,8 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace QRCodeService.Models
|
namespace QRCodeService.Models
|
||||||
{
|
{
|
||||||
public class CreateLinkModel
|
public class CreateLinkModel: CheckSignModel
|
||||||
{
|
{
|
||||||
public string SuffixUrl { get; set; }
|
public string SuffixUrl { get; set; }
|
||||||
public string Time { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -71,8 +71,10 @@ namespace QRCodeService
|
|||||||
//Repository
|
//Repository
|
||||||
services.AddScoped<IAppRepository, AppRepository>();
|
services.AddScoped<IAppRepository, AppRepository>();
|
||||||
services.AddScoped<ILinkRepository, LinkRepository>();
|
services.AddScoped<ILinkRepository, LinkRepository>();
|
||||||
|
//Queries
|
||||||
services.AddScoped<ILinkQueries, LinkQueries>();
|
services.AddScoped<ILinkQueries, LinkQueries>();
|
||||||
|
services.AddScoped<IAppQueries, AppQueries>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
|||||||
Reference in New Issue
Block a user