docs: 完善文档

This commit is contained in:
Fu Diwei
2021-12-01 22:06:50 +08:00
parent 68cbe5b63a
commit 2b1c41f968

View File

@@ -129,7 +129,7 @@ client.EncryptRequestSensitiveProperty(request);
上一小节提到,你可自行继承并实现一个 `CertificateManager`,例如利用数据库或 Redis 等方式存取证书信息。 上一小节提到,你可自行继承并实现一个 `CertificateManager`,例如利用数据库或 Redis 等方式存取证书信息。
下面给出一个利用 Redis 存储的示例代码: 下面给出一个利用 Redis 的 HASH 数据结构存储的示例代码:
```csharp ```csharp
using StackExchange.Redis; using StackExchange.Redis;
@@ -139,41 +139,76 @@ public class RedisCertificateManager : CertificateManager
{ {
private const string REDIS_KEY_PREFIX = "wxpaypc-"; private const string REDIS_KEY_PREFIX = "wxpaypc-";
protected ConnectionMultiplexer Connection { get; } private readonly ConnectionMultiplexer Connection { get; }
public RedisCertificateManager(string connectionString) public RedisCertificateManager(string connectionString)
{ {
Connection = ConnectionMultiplexer.Connect(connectionString); Connection = ConnectionMultiplexer.Connect(connectionString);
} }
protected string GenerateRedisKey(string serialNumber) private string GenerateRedisKey(string serialNumber)
{ {
return $"{REDIS_KEY_PREFIX}{serialNumber}"; return $"{REDIS_KEY_PREFIX}{serialNumber}";
} }
private CertificateEntry ConvertHashEntriesToCertificateEntry(HashEntry[] values)
{
if (values == null) throw new ArgumentNullException(nameof(values));
IDictionary<string, string> map = values.ToDictionary(k => k.Name.ToString(), v => v.Value.ToString());
return new CertificateEntry(
serialNumber: map[nameof(CertificateEntry.SerialNumber)],
certificate: map[nameof(CertificateEntry.Certificate)],
effectiveTime: DateTimeOffset.Parse(map[nameof(CertificateEntry.EffectiveTime)]),
expireTime: DateTimeOffset.Parse(map[nameof(CertificateEntry.ExpireTime)])
);
}
private HashEntry[] ConvertCertificateEntryToHashEntries(CertificateEntry entry)
{
return new HashEntry[]
{
new HashEntry(nameof(CertificateEntry.SerialNumber), entry.SerialNumber),
new HashEntry(nameof(CertificateEntry.Certificate), entry.Certificate),
new HashEntry(nameof(CertificateEntry.EffectiveTime), entry.EffectiveTime.ToString()),
new HashEntry(nameof(CertificateEntry.ExpireTime), entry.ExpireTime.ToString())
};
}
public override IEnumerable<CertificateEntry> AllEntries() public override IEnumerable<CertificateEntry> AllEntries()
{ {
// 生产环境中不应该使用 Redis KEYS 命令,这里代码仅作参考 // 生产环境中不应该使用 Redis KEYS 命令,这里代码仅作参考
// 你可以使用 SCAN + CURSOR 来实现类似功能
RedisKey[] keys = Connection.GetServer().Keys($"{REDIS_KEY_PREFIX}*"); RedisKey[] keys = Connection.GetServer().Keys($"{REDIS_KEY_PREFIX}*");
RedisValue[] values = Connection.GetDatabase().StringGet(keys); if (keys.Any())
return values.Where(e => e.HasValue).Select(e => JsonConvert.DeserializeObject<CertificateEntry>(e.ToString())); {
Task[] pipelineTasks = keys.Select(key => Connection.GetDatabase().HashGetAllAsync(key)).ToArray();
Connection.WaitAll(pipelineTasks);
return pipelineTasks
.Where(t => t.IsCompletedSuccessfully && t.Result.Any())
.Select(t => ConvertHashEntriesToCertificateEntry(t.Result))
.ToArray();
}
return Array.Empty<CertificateEntry>();
} }
public override void AddEntry(CertificateEntry entry) public override void AddEntry(CertificateEntry entry)
{ {
string key = GenerateRedisKey(serialNumber); string key = GenerateRedisKey(serialNumber);
string value = JsonConvert.SerializeObject(entry); HashEntry[] values = ConvertCertificateEntryToHashEntries(entry);
TimeSpan expiresIn = entry.ExpireTime - DateTimeOffset.Now; Connection.GetDatabase().HashSet(key, values);
Connection.GetDatabase().StringSet(key, value, expiresIn); Connection.GetDatabase().KeyExpire(key, entry.ExpireTime - DateTimeOffset.Now);
} }
public override CertificateEntry? GetEntry(string serialNumber) public override CertificateEntry? GetEntry(string serialNumber)
{ {
string key = GenerateRedisKey(serialNumber); string key = GenerateRedisKey(serialNumber);
string value = Connection.GetDatabase().StringGet(GenerateRedisKey(serialNumber)); HashEntry[] values = Connection.GetDatabase().HashGetAll(key);
if (!string.IsNullOrEmpty(value)) if (values.Any())
{ {
return JsonConvert.DeserializeObject<CertificateEntry>(value); return ConvertHashEntriesToCertificateEntry(values);
} }
return null; return null;