Files
qhmes/yy-admin-master/YY.Admin.Services/Service/EquipmentDb/EquipmentDbWhitelist.cs

79 lines
3.1 KiB
C#
Raw Normal View History

using System.Text.RegularExpressions;
namespace YY.Admin.Services.Service.EquipmentDb;
/// <summary>
/// 设备库 SQL 白名单:仅允许访问 MCS 中间表白名单表。
/// </summary>
public static class EquipmentDbWhitelist
{
private static readonly HashSet<string> AllowedTables = new(StringComparer.OrdinalIgnoreCase)
{
"MCSToMES_Alarm", "MCSToMES_MixAlarm", "MCSToMES_MixAct", "MCSToMES_Act_Mill", "MCSToMES_MixBatch",
"MCSToMES_MixCon", "MCSToMES_MixCurve", "MCSToMES_MixStep", "MCSToMES_MixWeight",
"MCSToMES_MixExePlan", "MCSToMES_BinToMater", "MCSToMES_AutoXLLog", "MCSToMES_CheckScaleLog",
"MESToMCS_Material", "MESToMCS_MixPlan", "MESToMCS_Recipe",
"MESToMCS_Recipe_MixStep", "MESToMCS_Recipe_Weight"
};
private static readonly Regex Dangerous = new(
@"\b(DROP|ALTER|TRUNCATE|EXEC|EXECUTE|xp_|sp_|INTO\s+OUTFILE|OPENROWSET|OPENDATASOURCE)\b",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex TableRef = new(
@"\b(?:FROM|INTO|UPDATE|JOIN)\s+\[?(?<t>[A-Za-z0-9_]+)\]?",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static bool IsAllowedTable(string? table)
{
if (string.IsNullOrWhiteSpace(table))
{
return false;
}
return AllowedTables.Contains(table.Trim());
}
public static void ValidateSql(string? sql, string? tableHint = null)
{
if (string.IsNullOrWhiteSpace(sql))
{
throw new InvalidOperationException("SQL 不能为空");
}
if (Dangerous.IsMatch(sql))
{
throw new InvalidOperationException("SQL 包含禁止关键字");
}
var trimmed = sql.TrimStart();
var isSelect = trimmed.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase);
var isInsert = trimmed.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase);
var isUpdate = trimmed.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase);
var isDelete = trimmed.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase);
if (!(isSelect || isInsert || isUpdate || isDelete))
{
throw new InvalidOperationException("仅允许 SELECT/INSERT/UPDATE/DELETE");
}
if (!string.IsNullOrWhiteSpace(tableHint) && !IsAllowedTable(tableHint))
{
throw new InvalidOperationException($"表不在白名单: {tableHint}");
}
foreach (Match m in TableRef.Matches(sql))
{
var t = m.Groups["t"].Value;
if (string.Equals(t, "TOP", StringComparison.OrdinalIgnoreCase)
|| string.Equals(t, "SELECT", StringComparison.OrdinalIgnoreCase)
|| string.Equals(t, "SET", StringComparison.OrdinalIgnoreCase)
|| string.Equals(t, "VALUES", StringComparison.OrdinalIgnoreCase)
|| string.Equals(t, "WHERE", StringComparison.OrdinalIgnoreCase))
{
continue;
}
if (!IsAllowedTable(t))
{
throw new InvalidOperationException($"SQL 引用了未授权表: {t}");
}
}
}
}