| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- using System.Data.Common;
- using System.Security.Cryptography;
- using System.Text;
- namespace Admin.NET.Plugin.AiDOP.Service.S8.Rules;
- /// <summary>
- /// S8-DYNAMIC-SQLSUGAR-SCOPE-FACTORY-1:S8 data_source endpoint 规范化与 hash 派生。
- /// 纯字符串变换:
- /// 1) 用 DbConnectionStringBuilder 解析 raw endpoint 的 key/value(大小写无关);
- /// 2) 按 OrdinalIgnoreCase 全部 key lower-case 化,避免不同输入 case 导致 hash 漂移;
- /// 3) 补齐缺失参数(已有 key 不覆盖),与主库 Database.json 池层参数对齐:
- /// AllowPublicKeyRetrieval / Pooling / Minimum Pool Size / Maximum Pool Size /
- /// Connection Timeout / Connection Idle Timeout / Connection LifeTime;
- /// 4) 按 key 字母序输出 normalized canonical connection string;
- /// 5) 对 normalized 做 SHA256 → 64 字符小写 hex EndpointHash。
- /// 不访问数据库、不读写文件、不读 env、不输出连接串原文、不输出密码。
- /// 输入为空或空白时抛 ArgumentException,message 不携带 endpoint 原文。
- /// </summary>
- internal static class S8DataSourceEndpointNormalizer
- {
- public const string KeyAllowPublicKeyRetrieval = "allowpublickeyretrieval";
- public const string KeyPooling = "pooling";
- public const string KeyMinimumPoolSize = "minimum pool size";
- public const string KeyMaximumPoolSize = "maximum pool size";
- public const string KeyConnectionTimeout = "connection timeout";
- public const string KeyConnectionIdleTimeout = "connection idle timeout";
- public const string KeyConnectionLifeTime = "connection lifetime";
- private static readonly (string Key, string Value)[] _normalizeDefaults =
- {
- (KeyAllowPublicKeyRetrieval, "True"),
- (KeyPooling, "True"),
- (KeyMinimumPoolSize, "0"),
- (KeyMaximumPoolSize, "20"),
- (KeyConnectionTimeout, "10"),
- (KeyConnectionIdleTimeout, "180"),
- (KeyConnectionLifeTime, "300"),
- };
- public static S8DataSourceEndpointNormalizeResult Normalize(string rawEndpoint)
- {
- if (string.IsNullOrWhiteSpace(rawEndpoint))
- throw new ArgumentException("S8 data_source endpoint 不能为空或空白", nameof(rawEndpoint));
- var parsed = new DbConnectionStringBuilder { ConnectionString = rawEndpoint };
- // SortedDictionary(Ordinal) + 全部 key 小写化 → 相同语义 endpoint 落到相同 canonical 顺序,hash 稳定。
- var canonical = new SortedDictionary<string, string>(StringComparer.Ordinal);
- foreach (string key in parsed.Keys)
- {
- var canonicalKey = key.ToLowerInvariant();
- canonical[canonicalKey] = parsed[key]?.ToString() ?? string.Empty;
- }
- // 补齐缺失默认值;已有 key(如自定义 Maximum Pool Size)保留原值,不覆盖。
- foreach (var (defaultKey, defaultValue) in _normalizeDefaults)
- {
- if (!canonical.ContainsKey(defaultKey))
- canonical[defaultKey] = defaultValue;
- }
- // 用 DbConnectionStringBuilder 按 sorted key 顺序重组;其 ToString 自动处理 value quoting。
- var normalizedBuilder = new DbConnectionStringBuilder();
- foreach (var kv in canonical)
- normalizedBuilder[kv.Key] = kv.Value;
- var normalized = normalizedBuilder.ConnectionString;
- var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(normalized));
- var hashHex = Convert.ToHexString(bytes).ToLowerInvariant();
- return new S8DataSourceEndpointNormalizeResult(normalized, hashHex);
- }
- }
- /// <summary>
- /// S8 data_source endpoint 规范化结果。NormalizedConnectionString 用于建 SqlSugarScope;
- /// EndpointHash 是 SHA256(normalized) 的 64 字符小写 hex,调用方可取前 N 位派生 ConfigId。
- /// </summary>
- public readonly record struct S8DataSourceEndpointNormalizeResult(string NormalizedConnectionString, string EndpointHash);
|