Commit 8e73e6ff by ryun

Merge branch 'feature/SQL注入拦截' into release/v23.2.19高县版

parents cfd2cf3e 99470398
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
namespace Performance.Api
{
/// <summary>
/// 防止SQL注入
/// </summary>
public class AntiSqlInject
{
public static AntiSqlInject Instance { get; } = new();
/// <summary>
/// 初始化过滤方法
/// </summary>
static AntiSqlInject()
{
SqlKeywordsArray.AddRange(SqlSeparatKeywords.Split('|'));
SqlKeywordsArray.AddRange(Array.ConvertAll(SqlCommandKeywords.Split('|'), h => h + " "));
SqlKeywordsArray.AddRange(Array.ConvertAll(SqlCommandKeywords.Split('|'), h => " " + h));
}
//private const string SqlCommandKeywords = "and|exec|execute|insert|select|delete|update|count|chr|mid|master|char|declare|sitename|net user|xp_cmdshell|or|create|drop|table|from|grant|use|group_concat|column_name|information_schema.columns|table_schema|union|where|select|delete|update|orderhaving|having|by|count|*|truncate|like";
//private const string SqlSeparatKeywords = "'|;|--|\'|\"|/*|%|#";
//private static string StrKeyWord = "select|insert|delete|from|count(|drop table|update|truncate|asc(|mid(|char(|xp_cmdshell|exec|master|net local group administrators|net user|or|and";
//private static string StrSymbol = ";|(|)|[|]|{|}|%|@|*|'|!";
private const string SqlCommandKeywords = "*|and|asc(|by|char|char(|chr|column_name|count|count(|create|declare|delete|drop|drop table|exec|execute|from|grant|group_concat|having|information_schema.columns|insert|like|master|mid|mid(|net local group administrators|net user|or|orderhaving|select|sitename|table|table_schema|truncate|union|update|use|where|xp_cmdshell";
private const string SqlSeparatKeywords = "--|;|!|'|\"|(|)|[|]|{|}|@|*|/*|#|%";
private static readonly List<string> SqlKeywordsArray = new List<string>();
/// <summary>
/// 检查字符串是否安全,是否包含Sql注入关键字
/// <param name="input">被检查的字符串</param>
/// <returns>如果包含sql注入关键字,返回:false;否则返回:true</returns>
///</summary>
public bool IsSafetySql(string input)
{
if (string.IsNullOrWhiteSpace(input))
{
return true;
}
input = HttpUtility.UrlDecode(input).ToLower();
foreach (var sqlKeyword in SqlKeywordsArray)
{
if (input.IndexOf(sqlKeyword, StringComparison.Ordinal) >= 0)
{
return false;
}
}
return true;
}
/// <summary>
/// 返回安全字符串
/// </summary>
/// <param name="input">输入</param>
/// <returns>返回</returns>
public string GetSafetySql(string input)
{
if (string.IsNullOrEmpty(input))
{
return string.Empty;
}
if (IsSafetySql(input)) { return input; }
input = HttpUtility.UrlDecode(input).ToLower();
foreach (var sqlKeyword in SqlKeywordsArray)
{
if (input.IndexOf(sqlKeyword, StringComparison.Ordinal) >= 0)
{
input = input.Replace(sqlKeyword, string.Empty);
}
}
return input;
}
}
/// <summary>
/// SQL注入过滤器
/// </summary>
public class AntiSqlInjectFilter : IAsyncActionFilter
{
private readonly Application _application;
public AntiSqlInjectFilter(IOptions<Application> options)
{
_application = options.Value;
}
/// <inheritdoc />
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (_application.OpenAntiSqlInject == true)
{
var routePath = context.HttpContext.Request.Path.ToString();
if (_application.AntiSqlInjectRouteWhite?.Any(route => route.Equals(routePath,StringComparison.OrdinalIgnoreCase)) != true)
{
foreach (var value in context.ActionArguments.Where(w => w.Value != null).Select(w => w.Value))
{
//如果不是值类型或接口,不需要过滤
var pType = value.GetType();
if (!pType.IsClass) continue;
//对string类型过滤
if (value is string && !AntiSqlInject.Instance.IsSafetySql(value.ToString()))
{
var response = new ApiResponse(ResponseType.Dangerous, "危险操作已拦截");
context.Result = new ObjectResult(response);
return;
}
else
{
//是一个class,对class的属性中,string类型的属性进行过滤
var properties = pType.GetProperties();
foreach (var pp in properties)
{
var temp = pp.GetValue(value);
if (temp == null) continue;
if (temp is string && !AntiSqlInject.Instance.IsSafetySql(temp.ToString()))
{
var response = new ApiResponse(ResponseType.Dangerous, "危险操作已拦截");
context.Result = new ObjectResult(response);
return;
}
}
}
}
}
}
await next();
}
}
}
using FluentScheduler; using System;
using System.Globalization;
using System.Reflection;
using System.Text;
using FluentScheduler;
using FluentValidation; using FluentValidation;
using FluentValidation.AspNetCore; using FluentValidation.AspNetCore;
using MassTransit;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Http.Connections;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization; using Microsoft.AspNetCore.Mvc.Authorization;
...@@ -13,13 +15,8 @@ ...@@ -13,13 +15,8 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Performance.Api.Configurations; using Performance.Api.Configurations;
using Performance.DtoModels;
using Performance.Infrastructure; using Performance.Infrastructure;
using Performance.Services; using Performance.Services;
using System;
using System.Globalization;
using System.Reflection;
using System.Text;
namespace Performance.Api namespace Performance.Api
{ {
...@@ -54,7 +51,7 @@ public void ConfigureServices(IServiceCollection services) ...@@ -54,7 +51,7 @@ public void ConfigureServices(IServiceCollection services)
// 控制器访问添加认证 // 控制器访问添加认证
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build(); var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
option.Filters.Add(new AuthorizeFilter(policy)); option.Filters.Add(new AuthorizeFilter(policy));
option.Filters.Add<AntiSqlInjectFilter>();
option.Filters.Add<ActionsFilter>(); option.Filters.Add<ActionsFilter>();
option.Filters.Add<ExceptionsFilter>(); option.Filters.Add<ExceptionsFilter>();
}) })
......
...@@ -11,6 +11,13 @@ ...@@ -11,6 +11,13 @@
//"PerformanceConnectionString": "server=116.62.245.55;database=db_performance;uid=root;pwd=1234qwer;pooling=true;charset=utf8;convert zero datetime=true;port=3306;connection timeout=120;max pool size=512;allow user variables=true;" //"PerformanceConnectionString": "server=116.62.245.55;database=db_performance;uid=root;pwd=1234qwer;pooling=true;charset=utf8;convert zero datetime=true;port=3306;connection timeout=120;max pool size=512;allow user variables=true;"
}, },
"Application": { "Application": {
// 是否开启反SQL注入 默认关闭 true 开启 false 关闭
"OpenAntiSqlInject": true,
// 开启反SQL注入白名单地址
"AntiSqlInjectRouteWhite": [
"/api/account/login",
"/api/account/quick/login"
],
//登录过期时间 //登录过期时间
"ExpirationMinutes": "1200", "ExpirationMinutes": "1200",
//验证码过期 //验证码过期
......
...@@ -2574,6 +2574,38 @@ ...@@ -2574,6 +2574,38 @@
<param name="query"></param> <param name="query"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:Performance.Api.AntiSqlInject">
<summary>
防止SQL注入
</summary>
</member>
<member name="M:Performance.Api.AntiSqlInject.#cctor">
<summary>
初始化过滤方法
</summary>
</member>
<member name="M:Performance.Api.AntiSqlInject.IsSafetySql(System.String)">
<summary>
检查字符串是否安全,是否包含Sql注入关键字
<param name="input">被检查的字符串</param>
<returns>如果包含sql注入关键字,返回:false;否则返回:true</returns>
</summary>
</member>
<member name="M:Performance.Api.AntiSqlInject.GetSafetySql(System.String)">
<summary>
返回安全字符串
</summary>
<param name="input">输入</param>
<returns>返回</returns>
</member>
<member name="T:Performance.Api.AntiSqlInjectFilter">
<summary>
SQL注入过滤器
</summary>
</member>
<member name="M:Performance.Api.AntiSqlInjectFilter.OnActionExecutionAsync(Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext,Microsoft.AspNetCore.Mvc.Filters.ActionExecutionDelegate)">
<inheritdoc />
</member>
<member name="M:Performance.Api.BackgroundJob.Execute_Allot_Statistics(Performance.Services.TaskService,Performance.EntityModels.bg_task)"> <member name="M:Performance.Api.BackgroundJob.Execute_Allot_Statistics(Performance.Services.TaskService,Performance.EntityModels.bg_task)">
<summary> <summary>
每日汇报表汇总 每日汇报表汇总
......
...@@ -49,6 +49,16 @@ ...@@ -49,6 +49,16 @@
相对 相对
</summary> </summary>
</member> </member>
<member name="P:Performance.DtoModels.AppSettings.Application.OpenAntiSqlInject">
<summary>
是否开启反SQL注入 默认关闭 true 开启 false 关闭
</summary>
</member>
<member name="P:Performance.DtoModels.AppSettings.Application.AntiSqlInjectRouteWhite">
<summary>
开启反SQL注入白名单地址
</summary>
</member>
<member name="P:Performance.DtoModels.AppSettings.RateLimitingConfig.Endpoints"> <member name="P:Performance.DtoModels.AppSettings.RateLimitingConfig.Endpoints">
<summary> <summary>
路径 路径
......
...@@ -18,26 +18,6 @@ public class Application ...@@ -18,26 +18,6 @@ public class Application
/// 短信模板 /// 短信模板
/// </summary> /// </summary>
public string SmsTemplate { get; set; } public string SmsTemplate { get; set; }
///// <summary>
///// 护士长二次绩效管理员
///// </summary>
//public int NurseRole { get; set; }
///// <summary>
///// 科主任二次绩效管理员
///// </summary>
//public int DirectorRole { get; set; }
///// <summary>
///// 特殊科室二次绩效管理员
///// </summary>
//public int SpecialRole { get; set; }
///// <summary>
///// 数据收集角色(可查看所有)
///// </summary>
//public int[] CollectRoles { get; set; }
///// <summary>
///// 行政科室二次绩效管理员
///// </summary>
//public int OfficeRole { get; set; }
/// <summary> /// <summary>
/// 邮件指定接收人 /// 邮件指定接收人
/// </summary> /// </summary>
...@@ -50,5 +30,13 @@ public class Application ...@@ -50,5 +30,13 @@ public class Application
/// 相对 /// 相对
/// </summary> /// </summary>
public string HttpPath { get; set; } public string HttpPath { get; set; }
/// <summary>
/// 是否开启反SQL注入 默认关闭 true 开启 false 关闭
/// </summary>
public bool? OpenAntiSqlInject { get; set; }
/// <summary>
/// 开启反SQL注入白名单地址
/// </summary>
public string[] AntiSqlInjectRouteWhite { get; set; }
} }
} }
...@@ -17,6 +17,8 @@ public enum ResponseType ...@@ -17,6 +17,8 @@ public enum ResponseType
Warning = 9, Warning = 9,
WarningTable = 10, WarningTable = 10,
Dangerous = 75,
Expiration = 99, Expiration = 99,
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment