.NET Core-自定义配置源(加密文件)

ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddCryptoFile(Path.Combine(AppContext.BaseDirectory, "appsettings.json.crypto"), true);
});

ConfigurationBuilderExtension

    public static class ConfigurationBuilderExtension
    {
        public static IConfigurationBuilder AddCryptoFile(this IConfigurationBuilder configurationBuilder, string path, bool reloadOnChange)
        {
            configurationBuilder.Add(new CryptoFileConfigurationSource(path, reloadOnChange));
            return configurationBuilder;
        }
    }

CryptoFileConfigurationSource

    public class CryptoFileConfigurationSource : IConfigurationSource
    {
        /// <summary>
        /// 路径
        /// </summary>
        public string Path { get; set; }
        /// <summary>
        /// 是否启用热加载
        /// </summary>
        public bool ReloadOnChange { get; set; }
        public CryptoFileConfigurationSource(string path, bool reloadOnChange)
        {
            Path = path;
            ReloadOnChange = reloadOnChange;
        }
        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            return new CryptoFileConfigurationProvider(this);
        }
    }

CryptoFileConfigurationProvider

    public class CryptoFileConfigurationProvider : ConfigurationProvider
    {
        private static ConcurrentDictionary<string, string> CONFIG_CACHE = new ConcurrentDictionary<string, string>();
        private CryptoFileConfigurationSource _source = null;
        private string _random = string.Empty;
        public CryptoFileConfigurationProvider(CryptoFileConfigurationSource source)
        {
            this._source = source;
            string fileName = IOHelper.GetFileNameNoPath(_source.Path);
            string filePath = _source.Path.Replace(fileName, string.Empty);
            IFileProvider fileProvider = new PhysicalFileProvider(filePath);
            if (_source.ReloadOnChange)
            {
                ChangeToken.OnChange(
                      () => fileProvider.Watch(fileName),
                      () =>
                      {
                          Load();
                      });
            }
            else
            {
                Load();
            }
        }

        public override void Load()
        {
            if (!IOHelper.IsExistFilePath(_source.Path))
            {
                throw new ArgumentException($"{_source.Path}路径不存在");
            }
            string cryptoContent = IOHelper.GetFileContent(_source.Path);
            //解密cryptoContent,获取json
            string json = AESCryptoHelper.Decrypt(cryptoContent);
            byte[] bytes = Encoding.UTF8.GetBytes(json);
            MemoryStream ms = new MemoryStream(bytes);
            this.Data = JsonConfigurationFileParser.Parse(ms);
        }
    }

JsonConfigurationFileParser

    internal class JsonConfigurationFileParser
    {
        private JsonConfigurationFileParser() { }

        private readonly IDictionary<string, string> _data = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        private readonly Stack<string> _context = new Stack<string>();
        private string _currentPath;

        private JsonTextReader _reader;

        public static IDictionary<string, string> Parse(Stream input)
            => new JsonConfigurationFileParser().ParseStream(input);

        private IDictionary<string, string> ParseStream(Stream input)
        {
            _data.Clear();
            _reader = new JsonTextReader(new StreamReader(input));
            _reader.DateParseHandling = DateParseHandling.None;

            var jsonConfig = JObject.Load(_reader);

            VisitJObject(jsonConfig);

            return _data;
        }

        private void VisitJObject(JObject jObject)
        {
            foreach (var property in jObject.Properties())
            {
                EnterContext(property.Name);
                VisitProperty(property);
                ExitContext();
            }
        }

        private void VisitProperty(JProperty property)
        {
            VisitToken(property.Value);
        }

        private void VisitToken(JToken token)
        {
            switch (token.Type)
            {
                case JTokenType.Object:
                    VisitJObject(token.Value<JObject>());
                    break;

                case JTokenType.Array:
                    VisitArray(token.Value<JArray>());
                    break;

                case JTokenType.Integer:
                case JTokenType.Float:
                case JTokenType.String:
                case JTokenType.Boolean:
                case JTokenType.Bytes:
                case JTokenType.Raw:
                case JTokenType.Null:
                    VisitPrimitive(token.Value<JValue>());
                    break;

                default:
                    throw new Exception("format error");
            }
        }

        private void VisitArray(JArray array)
        {
            for (int index = 0; index < array.Count; index++)
            {
                EnterContext(index.ToString());
                VisitToken(array[index]);
                ExitContext();
            }
        }

        private void VisitPrimitive(JValue data)
        {
            var key = _currentPath;

            if (_data.ContainsKey(key))
            {
                throw new Exception("format error");
            }
            _data[key] = data.ToString(CultureInfo.InvariantCulture);
        }

        private void EnterContext(string context)
        {
            _context.Push(context);
            _currentPath = ConfigurationPath.Combine(_context.Reverse());
        }

        private void ExitContext()
        {
            _context.Pop();
            _currentPath = ConfigurationPath.Combine(_context.Reverse());
        }
    }

.NET Core-自定义配置源(加密文件)

上一篇:Js Array常用操作


下一篇:php发送与接收流文件(php://input)