using System.Text.RegularExpressions; namespace YY.Admin.Services.Service.EquipmentDb; /// /// 设备库 SQL 白名单:仅允许访问 MCS 中间表白名单表。 /// public static class EquipmentDbWhitelist { private static readonly HashSet 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+\[?(?[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}"); } } } }