log4net SQL配置:不写入web.config,隐藏连接字符串的替代方案
嘿,我来给你几个实用的方案,完美解决你不想把log4net SQL日志的连接字符串写进web.config的问题:
方案一:自定义AdoNetAppender动态设置连接字符串
这种方式不需要在配置文件里写连接字符串,而是通过继承log4net的AdoNetAppender,在初始化的时候从你的服务获取连接字符串:
首先创建自定义Appender类:
using log4net.Appender; namespace YourProjectNamespace { public class DynamicConnectionAdoNetAppender : AdoNetAppender { protected override void Initialize() { // 调用你的服务获取安全的连接字符串 this.ConnectionString = GetConnection(); base.Initialize(); } // 这里替换成你实际获取连接字符串的方法 private string GetConnection() { // 比如从密钥管理服务、环境变量或者其他安全渠道获取 return "YourSecureConnectionStringFromService"; } } }
然后在web.config里配置这个自定义Appender,不需要写connectionString属性:
<log4net> <appender name="DynamicSqlLogAppender" type="YourProjectNamespace.DynamicConnectionAdoNetAppender"> <commandText value="INSERT INTO Logs (LogDate, Level, Message) VALUES (@LogDate, @Level, @Message)" /> <!-- 配置日志参数,根据你的表结构调整 --> <parameter> <parameterName value="@LogDate" /> <dbType value="DateTime" /> <layout type="log4net.Layout.RawTimeStampLayout" /> </parameter> <parameter> <parameterName value="@Level" /> <dbType value="String" /> <size value="50" /> <layout type="log4net.Layout.PatternLayout" value="%level" /> </parameter> <parameter> <parameterName value="@Message" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout" value="%message" /> </parameter> </appender> <root> <level value="INFO" /> <appender-ref ref="DynamicSqlLogAppender" /> </root> </log4net>
方案二:完全通过代码配置log4net SQL日志
如果不想依赖web.config的log4net配置,可以直接用代码创建并配置AdoNetAppender,连接字符串直接从服务获取,全程不碰配置文件:
using log4net; using log4net.Appender; using log4net.Core; using log4net.Layout; using log4net.Repository.Hierarchy; using System.Data; public static class Log4NetInitializer { public static void ConfigureSqlLog() { var hierarchy = (Hierarchy)LogManager.GetRepository(); hierarchy.Configured = true; // 创建SQL Appender var sqlAppender = new AdoNetAppender(); // 从安全渠道获取连接字符串 sqlAppender.ConnectionString = GetConnection(); sqlAppender.CommandText = "INSERT INTO Logs (LogDate, Level, Message) VALUES (@LogDate, @Level, @Message)"; // 添加日志参数 sqlAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@LogDate", DbType = DbType.DateTime, Layout = new RawTimeStampLayout() }); sqlAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@Level", DbType = DbType.String, Size = 50, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%level")) }); sqlAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@Message", DbType = DbType.String, Size = 4000, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%message")) }); // 激活配置并添加到根日志器 sqlAppender.ActivateOptions(); hierarchy.Root.AddAppender(sqlAppender); hierarchy.Root.Level = Level.Info; hierarchy.Configured = true; } private static string GetConnection() { // 替换成你实际获取连接字符串的逻辑 return "YourSecureConnectionStringFromService"; } }
然后在项目启动时调用Log4NetInitializer.ConfigureSqlLog()即可,比如在Global.asax的Application_Start里执行。
方案三:使用自定义连接字符串解析器(适用于log4net 2.0+)
如果还是想保留web.config的log4net配置结构,但不想写连接字符串,可以自定义IConnectionStringResolver来动态解析连接字符串名称对应的实际连接:
首先实现解析器:
using log4net.Repository; public class SecureConnectionStringResolver : IConnectionStringResolver { public string ResolveConnectionString(string connectionStringName) { // 根据连接字符串名称返回实际的安全连接字符串 // 这里可以做逻辑判断,比如不同名称返回不同连接 return GetConnection(); } private static string GetConnection() { return "YourSecureConnectionStringFromService"; } }
然后在log4net初始化时设置这个解析器:
var logRepository = LogManager.GetRepository(); logRepository.ConnectionStringResolver = new SecureConnectionStringResolver(); // 加载web.config里的log4net配置 XmlConfigurator.Configure(logRepository);
此时web.config里的AdoNetAppender只需要写connectionStringName,不需要写具体的连接字符串:
<appender name="SqlAppender" type="log4net.Appender.AdoNetAppender"> <connectionStringName value="LogDbConnection" /> <!-- 其他参数配置和之前一致 --> </appender>
为什么你之前的方案不生效?
你之前通过反射修改ConfigurationManager.ConnectionStrings的方法,需要先在web.config里存在对应的连接字符串项,而且这种修改内部私有字段的方式非常不稳定——不同.NET版本的ConfigurationElement内部实现可能变化,还可能触发安全检查,所以完全不推荐用这种方式。
内容的提问来源于stack exchange,提问作者Joe

