新增速率限制,调整本地文件上传,服务监控IP取本机网络IP,仓储增加方法
This commit is contained in:
parent
d3556cc058
commit
ee9f6bacf3
@ -16,8 +16,10 @@ namespace Infrastructure
|
|||||||
|
|
||||||
types.GetProperty("CreateTime", flag)?.SetValue(source, DateTime.Now, null);
|
types.GetProperty("CreateTime", flag)?.SetValue(source, DateTime.Now, null);
|
||||||
types.GetProperty("AddTime", flag)?.SetValue(source, DateTime.Now, null);
|
types.GetProperty("AddTime", flag)?.SetValue(source, DateTime.Now, null);
|
||||||
types.GetProperty("CreateBy", flag)?.SetValue(source, context.GetName(), null);
|
types.GetProperty("CreateBy", flag)?.SetValue(source, context.GetUId(), null);
|
||||||
types.GetProperty("Create_by", flag)?.SetValue(source, context.GetName(), null);
|
types.GetProperty("CreateName", flag)?.SetValue(source, context.GetNickName(), null);
|
||||||
|
types.GetProperty("Create_by", flag)?.SetValue(source, context.GetUId(), null);
|
||||||
|
types.GetProperty("Create_name", flag)?.SetValue(source, context.GetNickName(), null);
|
||||||
types.GetProperty("UserId", flag)?.SetValue(source, context.GetUId(), null);
|
types.GetProperty("UserId", flag)?.SetValue(source, context.GetUId(), null);
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
@ -31,9 +33,10 @@ namespace Infrastructure
|
|||||||
|
|
||||||
types.GetProperty("UpdateTime", flag)?.SetValue(source, DateTime.Now, null);
|
types.GetProperty("UpdateTime", flag)?.SetValue(source, DateTime.Now, null);
|
||||||
types.GetProperty("Update_time", flag)?.SetValue(source, DateTime.Now, null);
|
types.GetProperty("Update_time", flag)?.SetValue(source, DateTime.Now, null);
|
||||||
types.GetProperty("UpdateBy", flag)?.SetValue(source, context.GetName(), null);
|
types.GetProperty("UpdateBy", flag)?.SetValue(source, context.GetUId(), null);
|
||||||
types.GetProperty("Update_by", flag)?.SetValue(source, context.GetName(), null);
|
types.GetProperty("Update_by", flag)?.SetValue(source, context.GetUId(), null);
|
||||||
|
types.GetProperty("UpdateName", flag)?.SetValue(source, context.GetNickName(), null);
|
||||||
|
types.GetProperty("Update_name", flag)?.SetValue(source, context.GetNickName(), null);
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using ZR.Admin.WebApi.Filters;
|
using ZR.Admin.WebApi.Filters;
|
||||||
@ -126,6 +128,15 @@ namespace ZR.Admin.WebApi.Controllers
|
|||||||
SysFile file = new();
|
SysFile file = new();
|
||||||
string fileExt = Path.GetExtension(formFile.FileName);//文件后缀
|
string fileExt = Path.GetExtension(formFile.FileName);//文件后缀
|
||||||
double fileSize = Math.Round(formFile.Length / 1024.0, 2);//文件大小KB
|
double fileSize = Math.Round(formFile.Length / 1024.0, 2);//文件大小KB
|
||||||
|
var scheme = HttpContext.Request.Scheme + "://";
|
||||||
|
var serverIP = HttpContext.Request.Host.Value;
|
||||||
|
if (WebHostEnvironment.IsProduction())
|
||||||
|
{
|
||||||
|
var host = await Dns.GetHostEntryAsync(Dns.GetHostName());
|
||||||
|
var ip = host.AddressList
|
||||||
|
.FirstOrDefault(it => it.AddressFamily == AddressFamily.InterNetwork);
|
||||||
|
serverIP = ip + ":" + Request.HttpContext.Connection.LocalPort;//获取服务器IP
|
||||||
|
}
|
||||||
|
|
||||||
if (OptionsSetting.Upload.NotAllowedExt.Contains(fileExt))
|
if (OptionsSetting.Upload.NotAllowedExt.Contains(fileExt))
|
||||||
{
|
{
|
||||||
@ -147,7 +158,8 @@ namespace ZR.Admin.WebApi.Controllers
|
|||||||
{
|
{
|
||||||
uploadDto.FileDir = OptionsSetting.Upload.LocalSavePath;
|
uploadDto.FileDir = OptionsSetting.Upload.LocalSavePath;
|
||||||
}
|
}
|
||||||
file = await SysFileService.SaveFileToLocal(savePath, uploadDto.FileName, uploadDto.FileDir, HttpContext.GetName(), formFile);
|
file = await SysFileService.SaveFileToLocal(savePath, uploadDto.FileName, uploadDto.FileDir,
|
||||||
|
HttpContext.GetName(), formFile, scheme + serverIP);
|
||||||
break;
|
break;
|
||||||
case StoreType.REMOTE:
|
case StoreType.REMOTE:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using ZR.Admin.WebApi.Filters;
|
using ZR.Admin.WebApi.Filters;
|
||||||
using ZR.Model.System;
|
using ZR.Model.System;
|
||||||
@ -119,7 +121,18 @@ namespace ZR.Admin.WebApi.Controllers.System
|
|||||||
long userId = HttpContext.GetUId();
|
long userId = HttpContext.GetUId();
|
||||||
if (formFile == null) throw new CustomException("请选择文件");
|
if (formFile == null) throw new CustomException("请选择文件");
|
||||||
|
|
||||||
SysFile file = await FileService.SaveFileToLocal(hostEnvironment.WebRootPath, "", "avatar", HttpContext.GetName(), formFile);
|
var scheme = HttpContext.Request.Scheme + "://";
|
||||||
|
var serverIP = HttpContext.Request.Host.Value;
|
||||||
|
if (hostEnvironment.IsProduction())
|
||||||
|
{
|
||||||
|
var host = await Dns.GetHostEntryAsync(Dns.GetHostName());
|
||||||
|
var ip = host.AddressList
|
||||||
|
.FirstOrDefault(it => it.AddressFamily == AddressFamily.InterNetwork);
|
||||||
|
serverIP = ip + ":" + Request.HttpContext.Connection.LocalPort;//获取服务器IP
|
||||||
|
}
|
||||||
|
|
||||||
|
var file = await FileService.SaveFileToLocal(hostEnvironment.WebRootPath, "", "avatar",
|
||||||
|
HttpContext.GetName(), formFile, serverIP);
|
||||||
|
|
||||||
UserService.UpdatePhoto(new SysUser() { Avatar = file.AccessUrl, UserId = userId });
|
UserService.UpdatePhoto(new SysUser() { Avatar = file.AccessUrl, UserId = userId });
|
||||||
return SUCCESS(new { imgUrl = file.AccessUrl });
|
return SUCCESS(new { imgUrl = file.AccessUrl });
|
||||||
|
|||||||
@ -0,0 +1,195 @@
|
|||||||
|
using AspNetCoreRateLimit;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using ZR.Admin.WebApi.Filters;
|
||||||
|
using ZR.Model;
|
||||||
|
using ZR.ServiceCore.Model;
|
||||||
|
using ZR.ServiceCore.Services.IService;
|
||||||
|
using IpRateLimitPolicy = ZR.ServiceCore.Model.IpRateLimitPolicy;
|
||||||
|
|
||||||
|
namespace ZR.Admin.WebApi.Controllers.System.monitor;
|
||||||
|
|
||||||
|
[Verify]
|
||||||
|
[Route("ip/route/limit")]
|
||||||
|
public class IpRateLimitController : BaseController
|
||||||
|
{
|
||||||
|
private readonly IpRateLimitOptions _options;
|
||||||
|
private readonly IIpPolicyStore _ipPolicyStore;
|
||||||
|
private readonly IIpRateLimitPolicyService _ipRateLimitPolicyService;
|
||||||
|
private readonly IRateLimitRuleService _rateLimitRuleService;
|
||||||
|
private readonly IIpRateLimitLogService _ipRateLimitLogService;
|
||||||
|
|
||||||
|
public IpRateLimitController(IOptions<IpRateLimitOptions> optionsAccessor, IIpPolicyStore ipPolicyStore,
|
||||||
|
IIpRateLimitPolicyService ipRateLimitPolicyService, IRateLimitRuleService rateLimitRuleService,
|
||||||
|
IIpRateLimitLogService ipRateLimitLogService)
|
||||||
|
{
|
||||||
|
_options = optionsAccessor.Value;
|
||||||
|
_ipPolicyStore = ipPolicyStore;
|
||||||
|
_ipRateLimitPolicyService = ipRateLimitPolicyService;
|
||||||
|
_rateLimitRuleService = rateLimitRuleService;
|
||||||
|
_ipRateLimitLogService = ipRateLimitLogService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取限制规则
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("getIpRateLimitPolicyPage")]
|
||||||
|
public async Task<IActionResult> GetIpRateLimitPolicyPage([FromQuery] IpRateLimitPolicy ipRateLimitPolicy,
|
||||||
|
PagerInfo pager)
|
||||||
|
{
|
||||||
|
var page = await _ipRateLimitPolicyService.SelectIpRateLimitPolicyPageAsync(ipRateLimitPolicy, pager);
|
||||||
|
return SUCCESS(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("addIpRateLimitPolicy")]
|
||||||
|
public async Task<IActionResult> AddIpRateLimitPolicy([FromBody] IpRateLimitPolicy ipRateLimitPolicy)
|
||||||
|
{
|
||||||
|
var isExist = await _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Where(it => it.Ip == ipRateLimitPolicy.Ip)
|
||||||
|
.AnyAsync();
|
||||||
|
if (isExist) throw new CustomException("该IP已存在");
|
||||||
|
var res = await _ipRateLimitPolicyService.InsertNav(ipRateLimitPolicy)
|
||||||
|
.Include(it => it.Rules)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
return SUCCESS(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("updateIpRateLimitPolicy")]
|
||||||
|
public async Task<IActionResult> UpdateIpRateLimitPolicy(
|
||||||
|
[FromBody] IpRateLimitPolicy ipRateLimitPolicy)
|
||||||
|
{
|
||||||
|
var isEnable = await _ipRateLimitPolicyService
|
||||||
|
.Queryable()
|
||||||
|
.Where(it => it.Id == ipRateLimitPolicy.Id
|
||||||
|
&& it.Flag == '1')
|
||||||
|
.AnyAsync();
|
||||||
|
var res = await _ipRateLimitPolicyService.UpdateNav(ipRateLimitPolicy)
|
||||||
|
.Include(it => it.Rules)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
if (!isEnable) return SUCCESS(res);
|
||||||
|
{
|
||||||
|
await _ipPolicyStore.RemoveAsync(_options.IpPolicyPrefix);
|
||||||
|
var ipRateLimitPolicies = _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Includes(it => it.Rules.Where(r => r.Flag == '1').ToList())
|
||||||
|
.Where(it => it.Flag == '1')
|
||||||
|
.ToListAsync()
|
||||||
|
.GetAwaiter().GetResult()
|
||||||
|
.Adapt<List<AspNetCoreRateLimit.IpRateLimitPolicy>>();
|
||||||
|
await _ipPolicyStore.SeedAsync();
|
||||||
|
var pol = await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
|
||||||
|
pol.IpRules.AddRange(ipRateLimitPolicies);
|
||||||
|
await _ipPolicyStore.SetAsync(_options.IpPolicyPrefix, pol);
|
||||||
|
}
|
||||||
|
return SUCCESS(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPatch("enableIpRateLimitPolicy/{id}")]
|
||||||
|
public async Task<IActionResult> EnableIpRateLimitPolicy([FromRoute] long id)
|
||||||
|
{
|
||||||
|
var isEnable = await _ipRateLimitPolicyService
|
||||||
|
.Queryable()
|
||||||
|
.Where(it => it.Id == id
|
||||||
|
&& it.Flag == '1')
|
||||||
|
.AnyAsync();
|
||||||
|
if (isEnable)
|
||||||
|
{
|
||||||
|
throw new CustomException("已启用,无法再次启用");
|
||||||
|
}
|
||||||
|
await _ipRateLimitPolicyService.Updateable(new IpRateLimitPolicy
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Flag = '1'
|
||||||
|
}).UpdateColumns(it => it.Flag)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
var ipRateLimitPolicy = await _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Includes(it => it.Rules.Where(r => r.Flag == '1').ToList())
|
||||||
|
.Where(it => it.Id == id)
|
||||||
|
.SingleAsync();
|
||||||
|
var pol = await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
|
||||||
|
pol.IpRules.Add(ipRateLimitPolicy.Adapt<AspNetCoreRateLimit.IpRateLimitPolicy>());
|
||||||
|
await _ipPolicyStore.SetAsync(_options.IpPolicyPrefix, pol);
|
||||||
|
return SUCCESS('1');
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPatch("disableIpRateLimitPolicy/{id}")]
|
||||||
|
public async Task<IActionResult> DisableIpRateLimitPolicy([FromRoute] long id)
|
||||||
|
{
|
||||||
|
var isEnable = await _ipRateLimitPolicyService
|
||||||
|
.Queryable()
|
||||||
|
.Where(it => it.Id == id
|
||||||
|
&& it.Flag == '1')
|
||||||
|
.AnyAsync();
|
||||||
|
if (!isEnable)
|
||||||
|
{
|
||||||
|
throw new CustomException("已禁用,无法再次禁用");
|
||||||
|
}
|
||||||
|
await _ipRateLimitPolicyService.Updateable(new IpRateLimitPolicy
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Flag = '0'
|
||||||
|
}).UpdateColumns(it => it.Flag)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
var ipRateLimitPolicies = _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Includes(it => it.Rules.Where(r => r.Flag == '1').ToList())
|
||||||
|
.Where(it => it.Flag == '1')
|
||||||
|
.ToListAsync()
|
||||||
|
.GetAwaiter().GetResult()
|
||||||
|
.Adapt<List<AspNetCoreRateLimit.IpRateLimitPolicy>>();
|
||||||
|
await _ipPolicyStore.RemoveAsync(_options.IpPolicyPrefix);
|
||||||
|
await _ipPolicyStore.SeedAsync();
|
||||||
|
var pol = await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
|
||||||
|
pol.IpRules.AddRange(ipRateLimitPolicies);
|
||||||
|
await _ipPolicyStore.SetAsync(_options.IpPolicyPrefix, pol);
|
||||||
|
return SUCCESS('0');
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("deleteIpRateLimitPolicy/{id}")]
|
||||||
|
public async Task DeleteIpRateLimitPolicyAsync([FromRoute] long id)
|
||||||
|
{
|
||||||
|
var isEnable = await _ipRateLimitPolicyService
|
||||||
|
.Queryable()
|
||||||
|
.Where(it => it.Id == id
|
||||||
|
&& it.Flag == '1')
|
||||||
|
.AnyAsync();
|
||||||
|
await _ipRateLimitPolicyService
|
||||||
|
.DeleteNav(it => it.Id == id)
|
||||||
|
.Include(it => it.Rules)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
if (isEnable)
|
||||||
|
{
|
||||||
|
var ipRateLimitPolicies = _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Includes(it => it.Rules.Where(r => r.Flag == '1').ToList())
|
||||||
|
.Where(it => it.Flag == '1')
|
||||||
|
.ToListAsync()
|
||||||
|
.GetAwaiter().GetResult()
|
||||||
|
.Adapt<List<AspNetCoreRateLimit.IpRateLimitPolicy>>();
|
||||||
|
await _ipPolicyStore.RemoveAsync(_options.IpPolicyPrefix);
|
||||||
|
await _ipPolicyStore.SeedAsync();
|
||||||
|
var pol = await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
|
||||||
|
pol.IpRules.AddRange(ipRateLimitPolicies);
|
||||||
|
await _ipPolicyStore.SetAsync(_options.IpPolicyPrefix, pol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("getIpRateLimitLogPage")]
|
||||||
|
public async Task<IActionResult> GetIpRateLimitLogPage([FromQuery] IpRateLimitLog ipRateLimitLog, PagerInfo pager)
|
||||||
|
{
|
||||||
|
return SUCCESS(await _ipRateLimitLogService.SelectIpRateLimitLogPageAsync(ipRateLimitLog, pager));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("get")]
|
||||||
|
public async Task<IpRateLimitPolicies> Get()
|
||||||
|
{
|
||||||
|
return await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("checkIp/{ip}")]
|
||||||
|
public async Task<IActionResult> CheckIp(string ip)
|
||||||
|
{
|
||||||
|
var res = await _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Where(it => it.Ip == ip)
|
||||||
|
.AnyAsync();
|
||||||
|
return SUCCESS(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,8 @@ using Infrastructure.Extensions;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ZR.Admin.WebApi.Controllers.monitor
|
namespace ZR.Admin.WebApi.Controllers.monitor
|
||||||
@ -48,7 +50,11 @@ namespace ZR.Admin.WebApi.Controllers.monitor
|
|||||||
string appRAM = ((double)Process.GetCurrentProcess().WorkingSet64 / 1048576).ToString("N2") + " MB";
|
string appRAM = ((double)Process.GetCurrentProcess().WorkingSet64 / 1048576).ToString("N2") + " MB";
|
||||||
string startTime = Process.GetCurrentProcess().StartTime.ToString("yyyy-MM-dd HH:mm:ss");
|
string startTime = Process.GetCurrentProcess().StartTime.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
string sysRunTime = ComputerHelper.GetRunTime();
|
string sysRunTime = ComputerHelper.GetRunTime();
|
||||||
string serverIP = Request.HttpContext.Connection.LocalIpAddress.MapToIPv4().ToString() + ":" + Request.HttpContext.Connection.LocalPort;//获取服务器IP
|
// string serverIP = Request.HttpContext.Connection.LocalIpAddress.MapToIPv4().ToString() + ":" + Request.HttpContext.Connection.LocalPort;//获取服务器IP
|
||||||
|
var host = Dns.GetHostEntry(Dns.GetHostName());
|
||||||
|
var ip = host.AddressList
|
||||||
|
.FirstOrDefault(it => it.AddressFamily == AddressFamily.InterNetwork);
|
||||||
|
var serverIP = ip + ":" + Request.HttpContext.Connection.LocalPort;//获取服务器IP
|
||||||
|
|
||||||
var programStartTime = Process.GetCurrentProcess().StartTime;
|
var programStartTime = Process.GetCurrentProcess().StartTime;
|
||||||
string programRunTime = DateTimeHelper.FormatTime((DateTime.Now - programStartTime).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
|
string programRunTime = DateTimeHelper.FormatTime((DateTime.Now - programStartTime).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
|
||||||
|
|||||||
@ -69,6 +69,11 @@
|
|||||||
|
|
||||||
<!--写入黑洞-->
|
<!--写入黑洞-->
|
||||||
<target name="blackhole" xsi:type="Null" />
|
<target name="blackhole" xsi:type="Null" />
|
||||||
|
|
||||||
|
<target name="ipRateLimit" xsi:type="ColoredConsole" useDefaultRowHighlightingRules="false"
|
||||||
|
layout="${date:format=MM-dd HH\:mm\:ss} | ${aspnet-request-url} ${newline} ${message}">
|
||||||
|
<highlight-row condition="level == LogLevel.Info" foregroundColor="Blue" />
|
||||||
|
</target>
|
||||||
</targets>
|
</targets>
|
||||||
|
|
||||||
<rules>
|
<rules>
|
||||||
@ -82,7 +87,7 @@
|
|||||||
<logger name="*.SqlSugar.SqlsugarSetup" final="true" writeTo="consoleSql,sqlfile"/>
|
<logger name="*.SqlSugar.SqlsugarSetup" final="true" writeTo="consoleSql,sqlfile"/>
|
||||||
<logger name="*" minLevel="Trace" writeTo="allfile" />
|
<logger name="*" minLevel="Trace" writeTo="allfile" />
|
||||||
<logger name="*.GlobalExceptionMiddleware" final="true" writeTo="consoleSql,errorfile"/>
|
<logger name="*.GlobalExceptionMiddleware" final="true" writeTo="consoleSql,errorfile"/>
|
||||||
|
<logger name="ZR.Admin.WebApi.Middleware.CustomIpRateLimitMiddleware" final="true" writeTo="ipRateLimit" />
|
||||||
<!--Skip non-critical Microsoft logs and so log only own logs-->
|
<!--Skip non-critical Microsoft logs and so log only own logs-->
|
||||||
<logger name="Microsoft.*,Quartz.Core.QuartzSchedulerThread" maxlevel="Info" final="true" />
|
<logger name="Microsoft.*,Quartz.Core.QuartzSchedulerThread" maxlevel="Info" final="true" />
|
||||||
</rules>
|
</rules>
|
||||||
|
|||||||
@ -3,12 +3,13 @@ using Infrastructure.Converter;
|
|||||||
using Microsoft.AspNetCore.DataProtection;
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
using NLog.Web;
|
using NLog.Web;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
using Microsoft.Extensions.Caching.Redis;
|
using Microsoft.Extensions.Caching.Redis;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using ZR.Admin.WebApi.Extensions;
|
using ZR.Admin.WebApi.Extensions;
|
||||||
using ZR.Common.Cache;
|
using ZR.Common.Cache;
|
||||||
using ZR.Infrastructure.WebExtensions;
|
using ZR.Infrastructure.WebExtensions;
|
||||||
|
using ZR.ServiceCore.Services.IService;
|
||||||
using ZR.ServiceCore.Signalr;
|
using ZR.ServiceCore.Signalr;
|
||||||
using ZR.ServiceCore.SqlSugar;
|
using ZR.ServiceCore.SqlSugar;
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
|||||||
// 跨域配置
|
// 跨域配置
|
||||||
builder.Services.AddCors(builder.Configuration);
|
builder.Services.AddCors(builder.Configuration);
|
||||||
// 显示logo
|
// 显示logo
|
||||||
builder.Services.AddLogo();
|
// builder.Services.AddLogo();
|
||||||
//消除Error unprotecting the session cookie警告
|
//消除Error unprotecting the session cookie警告
|
||||||
builder.Services.AddDataProtection()
|
builder.Services.AddDataProtection()
|
||||||
.PersistKeysToFileSystem(new DirectoryInfo(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "DataProtection"));
|
.PersistKeysToFileSystem(new DirectoryInfo(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "DataProtection"));
|
||||||
@ -131,7 +132,8 @@ if (builder.Environment.IsProduction())
|
|||||||
//使用swagger
|
//使用swagger
|
||||||
app.UseSwagger();
|
app.UseSwagger();
|
||||||
//启用客户端IP限制速率
|
//启用客户端IP限制速率
|
||||||
app.UseIpRateLimiting();
|
// app.UseIpRateLimiting();
|
||||||
|
app.UseMiddleware<CustomIpRateLimitMiddleware>();
|
||||||
app.UseRateLimiter();
|
app.UseRateLimiter();
|
||||||
//设置socket连接
|
//设置socket连接
|
||||||
app.MapHub<MessageHub>("/msgHub");
|
app.MapHub<MessageHub>("/msgHub");
|
||||||
@ -141,4 +143,26 @@ app.MapControllerRoute(
|
|||||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||||
|
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
|
using (var serviceScope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var services = serviceScope.ServiceProvider;
|
||||||
|
|
||||||
|
// get the IpPolicyStore instance
|
||||||
|
var ipPolicyStore = services.GetRequiredService<IIpPolicyStore>();
|
||||||
|
|
||||||
|
// seed IP data from appsettings
|
||||||
|
ipPolicyStore.SeedAsync().GetAwaiter().GetResult();
|
||||||
|
|
||||||
|
var optionsAccessor = services.GetRequiredService<IOptions<IpRateLimitOptions>>();
|
||||||
|
var ipRateLimitPolicyService = services.GetRequiredService<IIpRateLimitPolicyService>();
|
||||||
|
var ipRateLimitPolicies = ipRateLimitPolicyService.Queryable()
|
||||||
|
.Includes(it => it.Rules.Where(r => r.Flag == '1').ToList())
|
||||||
|
.Where(it => it.Flag == '1')
|
||||||
|
.ToListAsync().GetAwaiter().GetResult();
|
||||||
|
var pol = await ipPolicyStore.GetAsync(optionsAccessor.Value.IpPolicyPrefix);
|
||||||
|
pol.IpRules.AddRange(ipRateLimitPolicies.Adapt<List<IpRateLimitPolicy>>());
|
||||||
|
await ipPolicyStore.SetAsync(optionsAccessor.Value.IpPolicyPrefix, pol);
|
||||||
|
}
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
@ -58,13 +58,37 @@ namespace ZR.Repository
|
|||||||
{
|
{
|
||||||
return Context.Insertable(t);
|
return Context.Insertable(t);
|
||||||
}
|
}
|
||||||
|
public IInsertable<T> Insertable(List<T> t)
|
||||||
|
{
|
||||||
|
return Context.Insertable<T>(t);
|
||||||
|
}
|
||||||
|
public IInsertable<T> Insertable(T[] t)
|
||||||
|
{
|
||||||
|
return Context.Insertable<T>(t);
|
||||||
|
}
|
||||||
|
public InsertNavTaskInit<T, T> InsertNav(T t)
|
||||||
|
{
|
||||||
|
return Context.InsertNav(t);
|
||||||
|
}
|
||||||
|
public InsertNavTaskInit<T, T> InsertNav(List<T> t)
|
||||||
|
{
|
||||||
|
return Context.InsertNav(t);
|
||||||
|
}
|
||||||
#endregion add
|
#endregion add
|
||||||
|
|
||||||
#region update
|
#region update
|
||||||
//public IUpdateable<T> Updateable(T entity)
|
public IUpdateable<T> Updateable(T entity)
|
||||||
//{
|
{
|
||||||
// return Context.Updateable(entity);
|
return Context.Updateable(entity);
|
||||||
//}
|
}
|
||||||
|
public IUpdateable<T> Updateable(List<T> t)
|
||||||
|
{
|
||||||
|
return Context.Updateable<T>(t);
|
||||||
|
}
|
||||||
|
public IUpdateable<T> Updateable(T[] t)
|
||||||
|
{
|
||||||
|
return Context.Updateable<T>(t);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 实体根据主键更新
|
/// 实体根据主键更新
|
||||||
@ -114,7 +138,25 @@ namespace ZR.Repository
|
|||||||
{
|
{
|
||||||
return Context.Updateable<T>().SetColumns(columns).Where(where).RemoveDataCache().ExecuteCommand();
|
return Context.Updateable<T>().SetColumns(columns).Where(where).RemoveDataCache().ExecuteCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UpdateNavTaskInit<T, T> UpdateNav(T t)
|
||||||
|
{
|
||||||
|
return Context.UpdateNav(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdateNavTaskInit<T, T> UpdateNav(List<T> t)
|
||||||
|
{
|
||||||
|
return Context.UpdateNav(t);
|
||||||
|
}
|
||||||
#endregion update
|
#endregion update
|
||||||
|
public IStorageable<T> Storageable(T t)
|
||||||
|
{
|
||||||
|
return Context.Storageable<T>(t);
|
||||||
|
}
|
||||||
|
public IStorageable<T> Storageable(List<T> t)
|
||||||
|
{
|
||||||
|
return Context.Storageable(t);
|
||||||
|
}
|
||||||
|
|
||||||
public DbResult<bool> UseTran(Action action)
|
public DbResult<bool> UseTran(Action action)
|
||||||
{
|
{
|
||||||
@ -190,6 +232,10 @@ namespace ZR.Repository
|
|||||||
{
|
{
|
||||||
return Context.DbMaintenance.TruncateTable<T>();
|
return Context.DbMaintenance.TruncateTable<T>();
|
||||||
}
|
}
|
||||||
|
public DeleteNavTaskInit<T, T> DeleteNav(Expression<Func<T, bool>> whereExpression)
|
||||||
|
{
|
||||||
|
return Context.DeleteNav(whereExpression);
|
||||||
|
}
|
||||||
#endregion delete
|
#endregion delete
|
||||||
|
|
||||||
#region query
|
#region query
|
||||||
|
|||||||
@ -16,9 +16,17 @@ namespace ZR.Repository
|
|||||||
int Insert(T parm, Expression<Func<T, object>> iClumns = null, bool ignoreNull = true);
|
int Insert(T parm, Expression<Func<T, object>> iClumns = null, bool ignoreNull = true);
|
||||||
|
|
||||||
IInsertable<T> Insertable(T t);
|
IInsertable<T> Insertable(T t);
|
||||||
|
IInsertable<T> Insertable(List<T> t);
|
||||||
|
IInsertable<T> Insertable(T[] t);
|
||||||
|
InsertNavTaskInit<T, T> InsertNav(T t);
|
||||||
|
InsertNavTaskInit<T, T> InsertNav(List<T> t);
|
||||||
#endregion add
|
#endregion add
|
||||||
|
|
||||||
#region update
|
#region update
|
||||||
|
IUpdateable<T> Updateable(T entity);
|
||||||
|
IUpdateable<T> Updateable(List<T> t);
|
||||||
|
IUpdateable<T> Updateable(T[] t);
|
||||||
|
|
||||||
int Update(T entity, bool ignoreNullColumns = false, object data = null);
|
int Update(T entity, bool ignoreNullColumns = false, object data = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -33,7 +41,13 @@ namespace ZR.Repository
|
|||||||
|
|
||||||
int Update(Expression<Func<T, bool>> where, Expression<Func<T, T>> columns);
|
int Update(Expression<Func<T, bool>> where, Expression<Func<T, T>> columns);
|
||||||
|
|
||||||
|
UpdateNavTaskInit<T, T> UpdateNav(T t);
|
||||||
|
|
||||||
|
UpdateNavTaskInit<T, T> UpdateNav(List<T> t);
|
||||||
#endregion update
|
#endregion update
|
||||||
|
IStorageable<T> Storageable(T t);
|
||||||
|
IStorageable<T> Storageable(List<T> t);
|
||||||
|
|
||||||
DbResult<bool> UseTran(Action action);
|
DbResult<bool> UseTran(Action action);
|
||||||
|
|
||||||
DbResult<bool> UseTran(SqlSugarClient client, Action action);
|
DbResult<bool> UseTran(SqlSugarClient client, Action action);
|
||||||
@ -46,7 +60,7 @@ namespace ZR.Repository
|
|||||||
int Delete(object id, string title = "");
|
int Delete(object id, string title = "");
|
||||||
int DeleteTable();
|
int DeleteTable();
|
||||||
bool Truncate();
|
bool Truncate();
|
||||||
|
DeleteNavTaskInit<T, T> DeleteNav(Expression<Func<T, bool>> whereExpression);
|
||||||
#endregion delete
|
#endregion delete
|
||||||
|
|
||||||
#region query
|
#region query
|
||||||
|
|||||||
47
ZR.ServiceCore/Middleware/CustomIpRateLimitMiddleware.cs
Normal file
47
ZR.ServiceCore/Middleware/CustomIpRateLimitMiddleware.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using AspNetCoreRateLimit;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using NLog;
|
||||||
|
using ZR.ServiceCore.Model;
|
||||||
|
using ZR.ServiceCore.Services.IService;
|
||||||
|
using RateLimitRule = AspNetCoreRateLimit.RateLimitRule;
|
||||||
|
|
||||||
|
namespace ZR.ServiceCore.Middleware;
|
||||||
|
|
||||||
|
public class CustomIpRateLimitMiddleware : IpRateLimitMiddleware
|
||||||
|
{
|
||||||
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
private readonly IIpRateLimitLogService _ipRateLimitLogService;
|
||||||
|
|
||||||
|
public CustomIpRateLimitMiddleware(RequestDelegate next, IProcessingStrategy processingStrategy,
|
||||||
|
IOptions<IpRateLimitOptions> options, IIpPolicyStore policyStore, IRateLimitConfiguration config,
|
||||||
|
ILogger<IpRateLimitMiddleware> logger, IIpRateLimitLogService ipRateLimitLogService) : base(next, processingStrategy, options, policyStore, config, logger)
|
||||||
|
{
|
||||||
|
_ipRateLimitLogService = ipRateLimitLogService;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity,
|
||||||
|
RateLimitCounter counter, RateLimitRule rule)
|
||||||
|
{
|
||||||
|
// base.LogBlockedRequest(httpContext, identity, counter, rule);
|
||||||
|
var nowDate = DateTime.Now;
|
||||||
|
var ipRateLimitLog = new IpRateLimitLog
|
||||||
|
{
|
||||||
|
HttpVerb = identity.HttpVerb,
|
||||||
|
Path = identity.Path,
|
||||||
|
ClientIp = identity.ClientIp,
|
||||||
|
Limit = rule.Limit,
|
||||||
|
Period = rule.Period,
|
||||||
|
Exceeded = counter.Count - rule.Limit,
|
||||||
|
Endpoint = rule.Endpoint,
|
||||||
|
CreateTime = nowDate
|
||||||
|
};
|
||||||
|
var logStr = $"请求 {ipRateLimitLog.HttpVerb}:{ipRateLimitLog.Path} 来自 IP {ipRateLimitLog.ClientIp} 已被阻止, " +
|
||||||
|
$"配额 {ipRateLimitLog.Limit}/{ipRateLimitLog.Period} 超出次数 {ipRateLimitLog.Exceeded}. " +
|
||||||
|
$"被规则 {ipRateLimitLog.Endpoint} 阻止. 时间: {ipRateLimitLog.CreateTime}";
|
||||||
|
Logger.Info(logStr);
|
||||||
|
_ipRateLimitLogService.InsertIpRateLimitLogAsync(ipRateLimitLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
ZR.ServiceCore/Model/IpRateLimitLog.cs
Normal file
26
ZR.ServiceCore/Model/IpRateLimitLog.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
namespace ZR.ServiceCore.Model;
|
||||||
|
|
||||||
|
[SugarTable("ip_rate_limit_log")]
|
||||||
|
[Tenant("0")]
|
||||||
|
public class IpRateLimitLog
|
||||||
|
{
|
||||||
|
[SugarColumn(IsPrimaryKey = true)]
|
||||||
|
[JsonConverter(typeof(ValueToStringConverter))]
|
||||||
|
public long Id { get; set;}
|
||||||
|
|
||||||
|
public string HttpVerb { get; set; }
|
||||||
|
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
public string ClientIp { get; set; }
|
||||||
|
|
||||||
|
public double Limit { get; set; }
|
||||||
|
|
||||||
|
public string Period { get; set; }
|
||||||
|
|
||||||
|
public double Exceeded { get; set; }
|
||||||
|
|
||||||
|
public string Endpoint { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
}
|
||||||
17
ZR.ServiceCore/Model/IpRateLimitPolicy.cs
Normal file
17
ZR.ServiceCore/Model/IpRateLimitPolicy.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
namespace ZR.ServiceCore.Model;
|
||||||
|
|
||||||
|
[SugarTable("ip_rate_limit_policy")]
|
||||||
|
[Tenant("0")]
|
||||||
|
public class IpRateLimitPolicy
|
||||||
|
{
|
||||||
|
[SugarColumn(IsPrimaryKey = true)]
|
||||||
|
[JsonConverter(typeof(ValueToStringConverter))]
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
public string Ip { get; set; }
|
||||||
|
|
||||||
|
[Navigate(NavigateType.OneToMany, nameof(RateLimitRule.IpRateLimitPolicyId))]
|
||||||
|
public List<RateLimitRule> Rules { get; set; }
|
||||||
|
|
||||||
|
public char Flag { get; set; } = '0';
|
||||||
|
}
|
||||||
21
ZR.ServiceCore/Model/RateLimitRule.cs
Normal file
21
ZR.ServiceCore/Model/RateLimitRule.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
namespace ZR.ServiceCore.Model;
|
||||||
|
|
||||||
|
[SugarTable("rate_limit_rule")]
|
||||||
|
[Tenant("0")]
|
||||||
|
public class RateLimitRule
|
||||||
|
{
|
||||||
|
[SugarColumn(IsPrimaryKey = true)]
|
||||||
|
[JsonConverter(typeof(ValueToStringConverter))]
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
[JsonConverter(typeof(ValueToStringConverter))]
|
||||||
|
public long IpRateLimitPolicyId { get; set; }
|
||||||
|
|
||||||
|
public string Endpoint { get; set; }
|
||||||
|
|
||||||
|
public string Period { get; set; }
|
||||||
|
|
||||||
|
public double Limit { get; set; }
|
||||||
|
|
||||||
|
public char Flag { get; set; } = '0';
|
||||||
|
}
|
||||||
20
ZR.ServiceCore/Model/SysLoginLimit.cs
Normal file
20
ZR.ServiceCore/Model/SysLoginLimit.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
namespace ZR.ServiceCore.Model;
|
||||||
|
|
||||||
|
[SugarTable("sys_login_limit")]
|
||||||
|
[Tenant("0")]
|
||||||
|
public class SysLoginLimit
|
||||||
|
{
|
||||||
|
[SugarColumn(IsPrimaryKey = true)]
|
||||||
|
[JsonConverter(typeof(ValueToStringConverter))]
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
public string UserName { get; set; }
|
||||||
|
|
||||||
|
public int? ErrorCount { get; set; }
|
||||||
|
|
||||||
|
public DateTime? ErrorTime { get; set; }
|
||||||
|
|
||||||
|
public string Ip { get; set; }
|
||||||
|
|
||||||
|
public char Flag { get; set; }
|
||||||
|
}
|
||||||
12
ZR.ServiceCore/Services/IService/IIpRateLimitLogService.cs
Normal file
12
ZR.ServiceCore/Services/IService/IIpRateLimitLogService.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using ZR.Model;
|
||||||
|
using ZR.Service;
|
||||||
|
using ZR.ServiceCore.Model;
|
||||||
|
|
||||||
|
namespace ZR.ServiceCore.Services.IService;
|
||||||
|
|
||||||
|
public interface IIpRateLimitLogService : IBaseService<IpRateLimitLog>
|
||||||
|
{
|
||||||
|
void InsertIpRateLimitLogAsync(IpRateLimitLog ipRateLimitLog);
|
||||||
|
|
||||||
|
Task<PagedInfo<IpRateLimitLog>> SelectIpRateLimitLogPageAsync(IpRateLimitLog ipRateLimitLog, PagerInfo pager);
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
using ZR.Model;
|
||||||
|
using ZR.Service;
|
||||||
|
using ZR.ServiceCore.Model;
|
||||||
|
|
||||||
|
namespace ZR.ServiceCore.Services.IService;
|
||||||
|
|
||||||
|
public interface IIpRateLimitPolicyService : IBaseService<IpRateLimitPolicy>
|
||||||
|
{
|
||||||
|
Task<PagedInfo<IpRateLimitPolicy>> SelectIpRateLimitPolicyPageAsync(IpRateLimitPolicy ipRateLimitPolicy,
|
||||||
|
PagerInfo pager);
|
||||||
|
|
||||||
|
}
|
||||||
11
ZR.ServiceCore/Services/IService/IRateLimitRuleService.cs
Normal file
11
ZR.ServiceCore/Services/IService/IRateLimitRuleService.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using ZR.Service;
|
||||||
|
using ZR.ServiceCore.Model;
|
||||||
|
|
||||||
|
namespace ZR.ServiceCore.Services.IService;
|
||||||
|
|
||||||
|
public interface IRateLimitRuleService : IBaseService<RateLimitRule>
|
||||||
|
{
|
||||||
|
Task<List<RateLimitRule>> DeleteRateLimitRuleAsync(long id);
|
||||||
|
|
||||||
|
Task<char> ChangeRateLimitRuleFlagAsync(long id);
|
||||||
|
}
|
||||||
@ -19,7 +19,7 @@ namespace ZR.Service.System.IService
|
|||||||
/// <param name="rootPath"></param>
|
/// <param name="rootPath"></param>
|
||||||
/// <param name="userName"></param>
|
/// <param name="userName"></param>
|
||||||
/// <returns>文件对象</returns>
|
/// <returns>文件对象</returns>
|
||||||
Task<SysFile> SaveFileToLocal(string rootPath, string fileName, string fileDir, string userName, IFormFile formFile);
|
Task<SysFile> SaveFileToLocal(string rootPath, string fileName, string fileDir, string userName, IFormFile formFile, string uploadUrl);
|
||||||
|
|
||||||
Task<SysFile> SaveFileToAliyun(SysFile file, IFormFile formFile);
|
Task<SysFile> SaveFileToAliyun(SysFile file, IFormFile formFile);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
11
ZR.ServiceCore/Services/IService/ISysLoginLimitService.cs
Normal file
11
ZR.ServiceCore/Services/IService/ISysLoginLimitService.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using ZR.Service;
|
||||||
|
using ZR.ServiceCore.Model;
|
||||||
|
|
||||||
|
namespace ZR.ServiceCore.Services.IService;
|
||||||
|
|
||||||
|
public interface ISysLoginLimitService : IBaseService<SysLoginLimit>
|
||||||
|
{
|
||||||
|
Task<bool> AddSysLoginLimitAsync(SysLoginLimit sysLoginLimit);
|
||||||
|
|
||||||
|
Task<bool> RemoveSysLoginLimitAsync(SysLoginLimit sysLoginLimit);
|
||||||
|
}
|
||||||
31
ZR.ServiceCore/Services/IpRateLimitLogService.cs
Normal file
31
ZR.ServiceCore/Services/IpRateLimitLogService.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using Infrastructure.Attribute;
|
||||||
|
using ZR.Model;
|
||||||
|
using ZR.Service;
|
||||||
|
using ZR.ServiceCore.Model;
|
||||||
|
using ZR.ServiceCore.Services.IService;
|
||||||
|
|
||||||
|
namespace ZR.ServiceCore.Services;
|
||||||
|
|
||||||
|
[AppService(ServiceType = typeof(IIpRateLimitLogService), ServiceLifetime = LifeTime.Transient)]
|
||||||
|
public class IpRateLimitLogService : BaseService<IpRateLimitLog>, IIpRateLimitLogService
|
||||||
|
{
|
||||||
|
public void InsertIpRateLimitLogAsync(IpRateLimitLog ipRateLimitLog)
|
||||||
|
{
|
||||||
|
Insertable(ipRateLimitLog).ExecuteReturnSnowflakeId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PagedInfo<IpRateLimitLog>> SelectIpRateLimitLogPageAsync(IpRateLimitLog ipRateLimitLog, PagerInfo pager)
|
||||||
|
{
|
||||||
|
RefAsync<int> total = 0;
|
||||||
|
var res = await Queryable()
|
||||||
|
.ToPageListAsync(pager.PageNum, pager.PageSize, total);
|
||||||
|
var page = new PagedInfo<IpRateLimitLog>
|
||||||
|
{
|
||||||
|
PageSize = pager.PageSize,
|
||||||
|
PageIndex = pager.PageNum,
|
||||||
|
Result = res,
|
||||||
|
TotalNum = total
|
||||||
|
};
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
ZR.ServiceCore/Services/IpRateLimitPolicyService.cs
Normal file
27
ZR.ServiceCore/Services/IpRateLimitPolicyService.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using Infrastructure.Attribute;
|
||||||
|
using ZR.Model;
|
||||||
|
using ZR.Service;
|
||||||
|
using ZR.ServiceCore.Services.IService;
|
||||||
|
using IpRateLimitPolicy = ZR.ServiceCore.Model.IpRateLimitPolicy;
|
||||||
|
|
||||||
|
namespace ZR.ServiceCore.Services;
|
||||||
|
|
||||||
|
[AppService(ServiceType = typeof(IIpRateLimitPolicyService), ServiceLifetime = LifeTime.Transient)]
|
||||||
|
public class IpRateLimitPolicyService : BaseService<IpRateLimitPolicy>, IIpRateLimitPolicyService
|
||||||
|
{
|
||||||
|
public async Task<PagedInfo<IpRateLimitPolicy>> SelectIpRateLimitPolicyPageAsync(IpRateLimitPolicy ipRateLimitPolicy, PagerInfo pager)
|
||||||
|
{
|
||||||
|
RefAsync<int> total = 0;
|
||||||
|
var res = await Queryable()
|
||||||
|
.Includes(it => it.Rules)
|
||||||
|
.ToPageListAsync(pager.PageNum, pager.PageSize, total);
|
||||||
|
var page = new PagedInfo<IpRateLimitPolicy>
|
||||||
|
{
|
||||||
|
PageSize = pager.PageSize,
|
||||||
|
PageIndex = pager.PageNum,
|
||||||
|
Result = res,
|
||||||
|
TotalNum = total
|
||||||
|
};
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
}
|
||||||
51
ZR.ServiceCore/Services/RateLimitRuleService.cs
Normal file
51
ZR.ServiceCore/Services/RateLimitRuleService.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using Infrastructure;
|
||||||
|
using Infrastructure.Attribute;
|
||||||
|
using ZR.Service;
|
||||||
|
using ZR.ServiceCore.Model;
|
||||||
|
using ZR.ServiceCore.Services.IService;
|
||||||
|
|
||||||
|
namespace ZR.ServiceCore.Services;
|
||||||
|
|
||||||
|
[AppService(ServiceType = typeof(IRateLimitRuleService), ServiceLifetime = LifeTime.Transient)]
|
||||||
|
public class RateLimitRuleService : BaseService<RateLimitRule>, IRateLimitRuleService
|
||||||
|
{
|
||||||
|
public async Task<List<RateLimitRule>> DeleteRateLimitRuleAsync(long id)
|
||||||
|
{
|
||||||
|
var isExist = await Queryable()
|
||||||
|
.Where(it => it.Id == id)
|
||||||
|
.SingleAsync();
|
||||||
|
if (isExist == null)
|
||||||
|
{
|
||||||
|
throw new CustomException("数据不存在,无法删除");
|
||||||
|
}
|
||||||
|
var del = await Deleteable()
|
||||||
|
.Where(it => it.Id == id)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
if (del <= 0) throw new CustomException("删除失败");
|
||||||
|
{
|
||||||
|
var res = await Queryable()
|
||||||
|
.Where(it => it.IpRateLimitPolicyId == isExist.IpRateLimitPolicyId)
|
||||||
|
.ToListAsync();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<char> ChangeRateLimitRuleFlagAsync(long id)
|
||||||
|
{
|
||||||
|
var isExist = await Queryable()
|
||||||
|
.Where(it => it.Id == id)
|
||||||
|
.SingleAsync();
|
||||||
|
if (isExist == null) throw new CustomException("数据不存在,无法更改");
|
||||||
|
var upd = await Updateable(new RateLimitRule
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Flag = isExist.Flag == '1' ? '0' : '1'
|
||||||
|
}).UpdateColumns(it => it.Flag)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
if (upd == 0) throw new CustomException("更改失败");
|
||||||
|
{
|
||||||
|
var res = isExist.Flag == '1' ? '0' : '1';
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -37,7 +37,7 @@ namespace ZR.Service.System
|
|||||||
/// <param name="formFile">上传的文件流</param>
|
/// <param name="formFile">上传的文件流</param>
|
||||||
/// <param name="userName"></param>
|
/// <param name="userName"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<SysFile> SaveFileToLocal(string rootPath, string fileName, string fileDir, string userName, IFormFile formFile)
|
public async Task<SysFile> SaveFileToLocal(string rootPath, string fileName, string fileDir, string userName, IFormFile formFile, string uploadUrl)
|
||||||
{
|
{
|
||||||
string fileExt = Path.GetExtension(formFile.FileName);
|
string fileExt = Path.GetExtension(formFile.FileName);
|
||||||
fileName = (fileName.IsEmpty() ? HashFileName() : fileName) + fileExt;
|
fileName = (fileName.IsEmpty() ? HashFileName() : fileName) + fileExt;
|
||||||
@ -55,7 +55,7 @@ namespace ZR.Service.System
|
|||||||
{
|
{
|
||||||
await formFile.CopyToAsync(stream);
|
await formFile.CopyToAsync(stream);
|
||||||
}
|
}
|
||||||
string uploadUrl = OptionsSetting.Upload.UploadUrl;
|
// string uploadUrl = OptionsSetting.Upload.UploadUrl;
|
||||||
string accessPath = string.Concat(uploadUrl, "/", filePath.Replace("\\", "/"), "/", fileName);
|
string accessPath = string.Concat(uploadUrl, "/", filePath.Replace("\\", "/"), "/", fileName);
|
||||||
SysFile file = new(formFile.FileName, fileName, fileExt, fileSize + "kb", filePath, userName)
|
SysFile file = new(formFile.FileName, fileName, fileExt, fileSize + "kb", filePath, userName)
|
||||||
{
|
{
|
||||||
|
|||||||
194
ZR.ServiceCore/Services/SysLoginLimitService.cs
Normal file
194
ZR.ServiceCore/Services/SysLoginLimitService.cs
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
using AspNetCoreRateLimit;
|
||||||
|
using Infrastructure;
|
||||||
|
using Infrastructure.Attribute;
|
||||||
|
using Mapster;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using ZR.Service;
|
||||||
|
using ZR.ServiceCore.Model;
|
||||||
|
using ZR.ServiceCore.Services.IService;
|
||||||
|
using IpRateLimitPolicy = ZR.ServiceCore.Model.IpRateLimitPolicy;
|
||||||
|
using RateLimitRule = ZR.ServiceCore.Model.RateLimitRule;
|
||||||
|
|
||||||
|
namespace ZR.ServiceCore.Services;
|
||||||
|
[AppService(ServiceType = typeof(ISysLoginLimitService), ServiceLifetime = LifeTime.Transient)]
|
||||||
|
public class SysLoginLimitService : BaseService<SysLoginLimit>, ISysLoginLimitService
|
||||||
|
{
|
||||||
|
private readonly IpRateLimitOptions _options;
|
||||||
|
|
||||||
|
private readonly IIpPolicyStore _ipPolicyStore;
|
||||||
|
|
||||||
|
private readonly IRateLimitRuleService _rateLimitRuleService;
|
||||||
|
|
||||||
|
private readonly IIpRateLimitPolicyService _ipRateLimitPolicyService;
|
||||||
|
|
||||||
|
public SysLoginLimitService(IIpPolicyStore ipPolicyStore, IOptions<IpRateLimitOptions> optionsAccessor,
|
||||||
|
IIpRateLimitPolicyService ipRateLimitPolicyService, IRateLimitRuleService rateLimitRuleService)
|
||||||
|
{
|
||||||
|
_ipPolicyStore = ipPolicyStore;
|
||||||
|
_ipRateLimitPolicyService = ipRateLimitPolicyService;
|
||||||
|
_rateLimitRuleService = rateLimitRuleService;
|
||||||
|
_options = optionsAccessor.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AddSysLoginLimitAsync(SysLoginLimit sysLoginLimit)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Context.Ado.BeginTranAsync();
|
||||||
|
var rateLimitRule = new RateLimitRule
|
||||||
|
{
|
||||||
|
Endpoint = "*",
|
||||||
|
Period = "1s",
|
||||||
|
Limit = 0,
|
||||||
|
Flag = '1'
|
||||||
|
};
|
||||||
|
var ipRateLimitPolicy = new IpRateLimitPolicy
|
||||||
|
{
|
||||||
|
Ip = sysLoginLimit.Ip,
|
||||||
|
Flag = '1',
|
||||||
|
Rules = new List<RateLimitRule>
|
||||||
|
{
|
||||||
|
rateLimitRule
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var existIpRateLimitPolicy = await _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Where(it => it.Ip == sysLoginLimit.Ip)
|
||||||
|
.FirstAsync();
|
||||||
|
if (existIpRateLimitPolicy != null)
|
||||||
|
{
|
||||||
|
rateLimitRule.IpRateLimitPolicyId = existIpRateLimitPolicy.Id;
|
||||||
|
var rateLimitRuleStore = await _rateLimitRuleService
|
||||||
|
.Storageable(rateLimitRule)
|
||||||
|
.WhereColumns(it => new
|
||||||
|
{
|
||||||
|
it.IpRateLimitPolicyId,
|
||||||
|
it.Endpoint,
|
||||||
|
it.Period,
|
||||||
|
it.Limit
|
||||||
|
})
|
||||||
|
.ToStorageAsync();
|
||||||
|
await rateLimitRuleStore.AsInsertable.ExecuteReturnSnowflakeIdAsync();
|
||||||
|
await rateLimitRuleStore.AsUpdateable
|
||||||
|
.IgnoreColumns(it => it.Id)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
if (existIpRateLimitPolicy.Flag != '1')
|
||||||
|
{
|
||||||
|
await _ipRateLimitPolicyService.Updateable(new IpRateLimitPolicy
|
||||||
|
{
|
||||||
|
Id = existIpRateLimitPolicy.Id,
|
||||||
|
Flag = '1'
|
||||||
|
}).UpdateColumns(it => it.Flag)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _ipRateLimitPolicyService.InsertNav(ipRateLimitPolicy)
|
||||||
|
.Include(it => it.Rules)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = await _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Includes(it => it.Rules.Where(r => r.Flag == '1').ToList())
|
||||||
|
.Where(it => it.Flag == '1')
|
||||||
|
.ToListAsync();
|
||||||
|
await _ipPolicyStore.RemoveAsync(_options.IpPolicyPrefix);
|
||||||
|
await _ipPolicyStore.SeedAsync();
|
||||||
|
var pol = await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
|
||||||
|
pol.IpRules.AddRange(res.Adapt<List<AspNetCoreRateLimit.IpRateLimitPolicy>>());
|
||||||
|
await _ipPolicyStore.SetAsync(_options.IpPolicyPrefix, pol);
|
||||||
|
await Updateable(new SysLoginLimit
|
||||||
|
{
|
||||||
|
Id = sysLoginLimit.Id,
|
||||||
|
Flag = '1'
|
||||||
|
}).UpdateColumns(it => it.Flag)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
await Context.Ado.CommitTranAsync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await Context.Ado.RollbackTranAsync();
|
||||||
|
var res = await _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Includes(it => it.Rules.Where(r => r.Flag == '1').ToList())
|
||||||
|
.Where(it => it.Flag == '1')
|
||||||
|
.ToListAsync();
|
||||||
|
await _ipPolicyStore.RemoveAsync(_options.IpPolicyPrefix);
|
||||||
|
await _ipPolicyStore.SeedAsync();
|
||||||
|
var pol = await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
|
||||||
|
pol.IpRules.AddRange(res.Adapt<List<AspNetCoreRateLimit.IpRateLimitPolicy>>());
|
||||||
|
await _ipPolicyStore.SetAsync(_options.IpPolicyPrefix, pol);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> RemoveSysLoginLimitAsync(SysLoginLimit sysLoginLimit)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Context.Ado.BeginTranAsync();
|
||||||
|
// 查询是否存在此IP的规则
|
||||||
|
var existIpRateLimitPolicy = await _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Where(it => it.Ip == sysLoginLimit.Ip)
|
||||||
|
.FirstAsync();
|
||||||
|
if (existIpRateLimitPolicy != null)
|
||||||
|
{
|
||||||
|
var rateLimitRule = new RateLimitRule
|
||||||
|
{
|
||||||
|
Endpoint = "*",
|
||||||
|
Period = "1s",
|
||||||
|
Limit = 0,
|
||||||
|
Flag = '0',
|
||||||
|
IpRateLimitPolicyId = existIpRateLimitPolicy.Id
|
||||||
|
};
|
||||||
|
var rateLimitRuleStore = await _rateLimitRuleService
|
||||||
|
.Storageable(rateLimitRule)
|
||||||
|
.WhereColumns(it => new
|
||||||
|
{
|
||||||
|
it.IpRateLimitPolicyId,
|
||||||
|
it.Endpoint,
|
||||||
|
it.Period,
|
||||||
|
it.Limit
|
||||||
|
})
|
||||||
|
.ToStorageAsync();
|
||||||
|
await rateLimitRuleStore.AsInsertable.ExecuteReturnSnowflakeIdAsync();
|
||||||
|
await rateLimitRuleStore.AsUpdateable
|
||||||
|
.IgnoreColumns(it => it.Id)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
var res = await _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Includes(it => it.Rules.Where(r => r.Flag == '1').ToList())
|
||||||
|
.Where(it => it.Flag == '1')
|
||||||
|
.ToListAsync();
|
||||||
|
await _ipPolicyStore.RemoveAsync(_options.IpPolicyPrefix);
|
||||||
|
await _ipPolicyStore.SeedAsync();
|
||||||
|
var pol = await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
|
||||||
|
pol.IpRules.AddRange(res.Adapt<List<AspNetCoreRateLimit.IpRateLimitPolicy>>());
|
||||||
|
await _ipPolicyStore.SetAsync(_options.IpPolicyPrefix, pol);
|
||||||
|
await Updateable(new SysLoginLimit
|
||||||
|
{
|
||||||
|
Id = sysLoginLimit.Id,
|
||||||
|
Flag = '0',
|
||||||
|
ErrorCount = 0
|
||||||
|
}).UpdateColumns(it => new { it.Flag, it.ErrorCount })
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
await Context.Ado.CommitTranAsync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
throw new CustomException("不存在此IP的规则");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await Context.Ado.RollbackTranAsync();
|
||||||
|
var res = await _ipRateLimitPolicyService.Queryable()
|
||||||
|
.Includes(it => it.Rules.Where(r => r.Flag == '1').ToList())
|
||||||
|
.Where(it => it.Flag == '1')
|
||||||
|
.ToListAsync();
|
||||||
|
await _ipPolicyStore.RemoveAsync(_options.IpPolicyPrefix);
|
||||||
|
await _ipPolicyStore.SeedAsync();
|
||||||
|
var pol = await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
|
||||||
|
pol.IpRules.AddRange(res.Adapt<List<AspNetCoreRateLimit.IpRateLimitPolicy>>());
|
||||||
|
await _ipPolicyStore.SetAsync(_options.IpPolicyPrefix, pol);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user