private const string StrRegex = @"<[^>]+?style=[\w]+?:expression\(|\b(alert|confirm|prompt)\b|^\+/v(8|9)|<[^>]*?=[^>]*?&#[^>]*?>|\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|/\*.+?\*/|<\s*script\b|<\s*img\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
private const string StrRegexSqlNew = "(?:')|(?:--)|(\\++)|(\\$)|(\\[])|(\\{})|(\\<>)|(/\\*(?:.|[\\n\\r])*?\\*/)|(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|sleep|where|exec)\\b)";
private const 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 const string StrSymbol = ";|%|*|'|!|`|~|#|$|^|&|*|()|=|{}|[]|;|<>|《》|?|--|++|‘|’";
//private const string StrRegex1 = @"<[^>]+?style=[\w]+?:expression\(|\b(alert|confirm|prompt)\b|^\+/v(8|9)|<[^>]*?=[^>]*?&#[^>]*?>|\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|/\*.+?\*/|<\s*script\b|<\s*img\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE|WHERE|EXEC|EXECUTE|SLEEP)";
//private const string StrRegexSql = "(?:')|(?:--)|(\\++)|(\\@)|(\\$)|(\\[])|(\\{})|(\\<>)|(/\\*(?:.|[\\n\\r])*?\\*/)|" + "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|sleep|where|exec)\\b)";//.*/i
检查方法:
/// <summary>
/// 检查注入sql
/// </summary>
/// <param name="inputData"></param>
/// <returns></returns>
private static bool CheckData(string inputData)
{
var sqlPattern = Regex.Matches(inputData, StrRegexSqlNew, RegexOptions.IgnoreCase);//表示忽略大小写
bool isMatch = sqlPattern.Any(x => x.Success);
if (Regex.IsMatch(inputData, StrRegex) || isMatch)
{
return true;
}
if (CheckKeyWord(inputData))
{
return true;
}
else
{
return false;
}
}
///<summary>
///检查字符串中是否包含Sql注入关键字
/// <param name="_key">被检查的字符串</param>
/// <returns>如果包含sql注入关键字,返回:true;否则返回:false</returns>
///</summary>
private static bool CheckKeyWord(string _key)
{
string[] pattenKeyWord = StrKeyWord.Split('|');
string[] pattenSymbol = StrSymbol.Split('|');
foreach (string sqlParam in pattenKeyWord)
{
if (_key.Contains(sqlParam + " ") || _key.Contains(" " + sqlParam))
{
return true;
}
}
foreach (string sqlParam in pattenSymbol)
{
if (_key.Contains(sqlParam))
{
return true;
}
}
return false;
}
请求dotnet Core Body Json对象参数办法:
1.
var actionParameters = context.ActionDescriptor.Parameters;
foreach (var p in actionParameters)
{
if (p.ParameterType == typeof(string))
{
if (context.ActionArguments.Count > 0 && context.ActionArguments[p.Name] != null)
{
var par = context.ActionArguments[p.Name].ToString();
var res = CheckData(par);
if (res)
{
var resMsg = new JsonResult(new { state = ResultStateEnum.Fail, message = $"请求的参数{p.Name} - 值{par}不合法!" });
resMsg.StatusCode = 400;
context.Result = resMsg;
}
}
}
}
2. 通过 context.ActionArguments 和 context.ActionDescriptor.Parameters;
public void OnActionExecuting(ActionExecutingContext context)
{
var descriptor = (ControllerActionDescriptor)context.ActionDescriptor;
//获取控制器名称
var controllerName = descriptor.ControllerName;
//获取action名称
var actionName = descriptor.ActionName;
//获取body内容
var content = JsonConvert.SerializeObject(context.ActionArguments);
//日志记录
Logger.Log.Info($"{controllerName}/{actionName},{content}");
}
3.通过Request.Body原始流获取http请求体json数据
a. 修改 Startup.cs 中的 Configure方法添加如下中间件 允许多次读取请求体
// 允许多次读取 HttpContext.Body 请求体流数据
app.Use(next => new RequestDelegate(
async context =>
{
context.Request.EnableBuffering();
await next(context);
})
);
b.
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (context.HttpContext.Request.Method.ToUpper() == "POST")
{
var stream = context.HttpContext.Request.Body;
if (stream != null)
{
string bodyStr = null;
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
stream.Seek(0, SeekOrigin.Begin);
bodyStr = await reader.ReadToEndAsync();
stream.Seek(0, SeekOrigin.Begin);
}
if (!bodyStr.IsEmpty())
{
if (VerifySign(JObject.Parse(bodyStr)))
{
// 验签成功才继续执行
await next();
return; // 执行完管道其他操作后立即返回
}
}
}
}
// 设置短路,返回响应
await HandleAsync(context.HttpContext, ResultModel.Create(ResutlCodeEnum.验签失败));
return;
}