Files
tiku-backend.net/Tiku.Application/Security/JwtOptions.cs
xiong c497a3ca8d
Some checks failed
ci / release-gate (push) Has been cancelled
清理代码
2026-08-03 12:31:39 +08:00

68 lines
2.1 KiB
C#

using System.ComponentModel.DataAnnotations;
using System.Security.Cryptography;
namespace Tiku.Application.Security;
public sealed class JwtOptions
{
[Required] public string Issuer { get; set; } = "tiku-backend";
[Required] public string Audience { get; set; } = "tiku-api";
[Required] public string KeyId { get; set; } = "development-ephemeral";
public string PrivateKeyPem { get; set; } = string.Empty;
public Dictionary<string, string> PublicKeys { get; set; } = new(StringComparer.Ordinal);
[Range(1, 1440)] public int AccessTokenMinutes { get; set; } = 15;
[Range(1, 365)] public int RefreshTokenDays { get; set; } = 30;
public static bool BeValid(JwtOptions options, bool isProduction)
{
if (string.IsNullOrWhiteSpace(options.Issuer) ||
string.IsNullOrWhiteSpace(options.Audience) ||
string.IsNullOrWhiteSpace(options.KeyId) ||
options.AccessTokenMinutes != 15 ||
(isProduction && string.Equals(
options.KeyId,
"development-ephemeral",
StringComparison.Ordinal)))
return false;
if (string.IsNullOrWhiteSpace(options.PrivateKeyPem))
{
if (isProduction) return false;
}
else if (!IsValidRsaPem(options.PrivateKeyPem, true))
{
return false;
}
return options.PublicKeys.All(pair =>
!string.IsNullOrWhiteSpace(pair.Key) &&
!string.Equals(pair.Key, options.KeyId, StringComparison.Ordinal) &&
IsValidRsaPem(pair.Value, false));
}
private static bool IsValidRsaPem(string pem, bool requirePrivateKey)
{
try
{
using var rsa = RSA.Create();
rsa.ImportFromPem(pem);
if (rsa.KeySize < 2048) return false;
if (requirePrivateKey) _ = rsa.ExportParameters(true);
return true;
}
catch (Exception exception) when (
exception is ArgumentException or
CryptographicException)
{
return false;
}
}
}