网站首页 网站源码
using MailKit;
namespace Dpz.Core.Service;
public sealed class SerilogProtocolLogger(ILogger<SerilogProtocolLogger> logger) : IProtocolLogger
{
private readonly EventId _eventId = new(10001, "邮件日志");
private static readonly byte[] Secret = "********"u8.ToArray();
private static readonly byte[] DefaultClientPrefix = "Client: "u8.ToArray();
private static readonly byte[] DefaultServerPrefix = "Server: "u8.ToArray();
private bool _clientMidline;
private bool _serverMidline;
private readonly MemoryStream _stream = new();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private bool _disposed;
private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_stream.Flush();
_stream.Position = 0;
using var reader = new StreamReader(_stream);
var message = reader.ReadToEnd();
logger.LogInformation(_eventId, message);
_stream.Dispose();
}
_disposed = true;
}
}
~SerilogProtocolLogger() => Dispose(false);
public void LogConnect(Uri uri)
{
var bytes = Encoding.ASCII.GetBytes($"{DateTime.Now} Connected to {uri}\r\n");
if (_clientMidline || _serverMidline)
{
_clientMidline = false;
_serverMidline = false;
}
_stream.Write(bytes, 0, bytes.Length);
_stream.Flush();
}
public void LogClient(byte[]? buffer, int offset, int count)
{
LogBuffer(buffer, offset, count, DefaultClientPrefix, ref _clientMidline, true);
}
public void LogServer(byte[]? buffer, int offset, int count)
{
LogBuffer(buffer, offset, count, DefaultServerPrefix, ref _serverMidline, false);
}
private void LogBuffer(
byte[]? buffer,
int offset,
int count,
byte[] prefix,
ref bool midline,
bool isClient
)
{
if (buffer == null)
{
logger.LogError(_eventId, "buffer is null");
return;
}
if (offset < 0 || offset > buffer.Length)
{
logger.LogError(
_eventId,
"offset less than 0 or offset greater than {Offset}",
buffer.Length
);
return;
}
if (count < 0 || count > buffer.Length - offset)
{
logger.LogError(
_eventId,
"count less than 0 or count greater than {Offset}",
buffer.Length - offset
);
return;
}
Log(prefix, ref midline, buffer, offset, count, isClient);
}
private void Log(
byte[] prefix,
ref bool midline,
byte[] buffer,
int offset,
int count,
bool isClient
)
{
var number = offset + count;
var index = offset;
while (index < number)
{
var offset1 = index;
while (index < number && buffer[index] != 10)
++index;
if (!midline)
{
_stream.Write(prefix, 0, prefix.Length);
}
if (index < number && buffer[index] == 10)
{
midline = false;
++index;
}
else
midline = true;
if (isClient)
{
var authenticationSecrets = AuthenticationSecretDetector?.DetectSecrets(
buffer,
offset1,
index - offset1
);
if (authenticationSecrets != null)
{
foreach (var detectSecret in authenticationSecrets)
{
if (detectSecret.StartIndex > offset1)
_stream.Write(buffer, offset1, detectSecret.StartIndex - offset1);
offset1 = detectSecret.StartIndex + detectSecret.Length;
_stream.Write(Secret, 0, Secret.Length);
}
}
}
_stream.Write(buffer, offset1, index - offset1);
}
}
public IAuthenticationSecretDetector? AuthenticationSecretDetector { get; set; }
}
这段代码定义了一个名为 SerilogProtocolLogger
的类,它实现了 IProtocolLogger
接口,主要用于记录邮件协议的日志。该类使用了 MailKit
库,并且通过 Serilog
进行日志记录。以下是代码的主要功能和结构的详细解释:
日志记录:
MemoryStream
),并在适当的时候将其内容记录到日志中。连接日志:
LogConnect(Uri uri)
方法记录与邮件服务器的连接信息,包括连接的时间和 URI。客户端和服务器日志:
LogClient(byte[]? buffer, int offset, int count)
和 LogServer(byte[]? buffer, int offset, int count)
方法分别用于记录客户端和服务器发送的数据。LogBuffer
方法来处理和记录数据。数据处理:
LogBuffer
方法负责检查输入的缓冲区是否有效,并调用 Log
方法来处理实际的日志记录。Log
方法会逐行处理数据,检查是否有换行符,并在每行前添加相应的前缀(客户端或服务器)。敏感信息检测:
Log
方法会使用 AuthenticationSecretDetector
来检测是否有敏感信息(如密码)被发送。如果检测到敏感信息,它会用一个占位符(Secret
)替换这些信息,以保护隐私。资源管理:
IDisposable
接口,以确保在不再需要时正确释放资源。Dispose
方法会在对象被销毁时调用,确保内存流被正确处理并记录日志。字段和属性:
_eventId
:用于标识日志事件的 ID。Secret
:一个字节数组,用于替换敏感信息。DefaultClientPrefix
和 DefaultServerPrefix
:用于标识客户端和服务器日志的前缀。_clientMidline
和 _serverMidline
:用于跟踪当前行是否已结束。_stream
:用于存储日志信息的内存流。AuthenticationSecretDetector
:可选的属性,用于检测敏感信息。构造函数:
SerilogProtocolLogger(ILogger<SerilogProtocolLogger> logger)
:构造函数接受一个 ILogger
实例,用于记录日志。析构函数:
~SerilogProtocolLogger()
:析构函数,确保在对象被垃圾回收时调用 Dispose
方法。SerilogProtocolLogger
类是一个用于记录邮件协议交互的日志记录器,能够处理连接信息、客户端和服务器之间的通信,并且能够检测和保护敏感信息。它通过 Serilog
进行日志记录,并实现了资源管理以确保内存的有效使用。