网站首页 网站源码
using System.Collections.Concurrent;
using System.Reflection;
using System.Security.Claims;
namespace Dpz.Core.Auth;
public static class AuthHelper
{
private static readonly HashSet<string> AllowedPermissionGroups = new(StringComparer.Ordinal)
{
"Endpoints",
"GrantTypes",
"ResponseTypes",
"Scopes",
};
public static readonly Lazy<Dictionary<string, List<string>>> OpenIddictPermissionCache = new(
GetPermissionGroups
);
private static Dictionary<string, List<string>> GetPermissionGroups()
{
const BindingFlags flags =
BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy;
var groups = new Dictionary<string, List<string>>(StringComparer.Ordinal);
foreach (
var t in typeof(OpenIddict.Abstractions.OpenIddictConstants.Permissions).GetNestedTypes()
)
{
if (!AllowedPermissionGroups.Contains(t.Name))
{
continue;
}
var values = t.GetFields(flags)
.Where(f =>
f is { IsLiteral: true, IsInitOnly: false } && f.FieldType == typeof(string)
)
.Select(f => (string)f.GetRawConstantValue()!)
.OrderBy(x => x, StringComparer.Ordinal)
.ToList();
if (values.Count > 0)
{
groups[t.Name] = values;
}
}
return groups;
}
private static readonly ConcurrentDictionary<string, string> AuthorizationDescription = new(
StringComparer.OrdinalIgnoreCase
);
private static readonly ConcurrentDictionary<string, string> TokenStatusDescription = new(
StringComparer.OrdinalIgnoreCase
);
private static readonly ConcurrentDictionary<string, string> TokenTypeDescription = new(
StringComparer.OrdinalIgnoreCase
);
static AuthHelper()
{
AuthorizationDescription.TryAdd("valid", "有效");
AuthorizationDescription.TryAdd("revoked", "已撤销");
AuthorizationDescription.TryAdd("inactive", "禁用");
AuthorizationDescription.TryAdd("ad-hoc", "临时授权");
AuthorizationDescription.TryAdd("permanent", "永久授权");
TokenStatusDescription.TryAdd("valid", "有效");
TokenStatusDescription.TryAdd("revoked", "已撤销");
TokenStatusDescription.TryAdd("expired", "已过期");
TokenStatusDescription.TryAdd("invalid", "无效");
TokenStatusDescription.TryAdd("inactive", "未激活");
TokenStatusDescription.TryAdd("used", "已使用");
TokenStatusDescription.TryAdd("replaced", "已替换");
TokenStatusDescription.TryAdd("redeemed", "已兑换");
TokenTypeDescription.TryAdd("access_token", "访问令牌");
TokenTypeDescription.TryAdd("refresh_token", "刷新令牌");
TokenTypeDescription.TryAdd("device_code", "设备码");
TokenTypeDescription.TryAdd("authorization_code", "授权码");
TokenTypeDescription.TryAdd("id_token", "身份令牌");
TokenTypeDescription.TryAdd("oidc_principal", "OIDC 主体令牌");
TokenTypeDescription.TryAdd("reference_token", "引用令牌");
TokenTypeDescription.TryAdd("personal_access_token", "个人访问令牌");
}
public static string GetAuthorizationDescription(string? key)
{
if (string.IsNullOrWhiteSpace(key))
{
return "-";
}
if (AuthorizationDescription.TryGetValue(key, out var value))
{
return value;
}
return key;
}
public static string GetTokenStatusDescription(string? key)
{
if (string.IsNullOrWhiteSpace(key))
{
return "-";
}
var dictKey = TokenStatusDescription.Keys.FirstOrDefault(x =>
key.EndsWith(x, StringComparison.OrdinalIgnoreCase)
);
if (dictKey == null)
{
return "-";
}
return TokenStatusDescription[dictKey];
}
public static string GetTokenTypeDescription(string? key)
{
if (string.IsNullOrWhiteSpace(key))
{
return "-";
}
var dictKey = TokenTypeDescription.Keys.FirstOrDefault(x =>
key.EndsWith(x, StringComparison.OrdinalIgnoreCase)
);
if (dictKey == null)
{
return "-";
}
return TokenTypeDescription[dictKey];
}
extension(ClaimsPrincipal principal)
{
/// <summary>
/// 账号 用户ID
/// </summary>
public string? NameIdentifier => principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
}
}
这段代码定义了一个名为 AuthHelper 的静态类,主要用于处理与身份验证和授权相关的功能。以下是代码的主要组成部分和功能的详细解释:
这是一个 HashSet<string>,包含了允许的权限组名称。它用于过滤在后续代码中处理的权限组。
这是一个 Lazy<Dictionary<string, List<string>>>,用于缓存 OpenIddict 的权限组。它在第一次访问时会调用 GetPermissionGroups 方法来填充数据。
这个私有方法使用反射来获取 OpenIddict 中的权限组。它会遍历 OpenIddict.Abstractions.OpenIddictConstants.Permissions 类的嵌套类型,并检查这些类型的名称是否在 AllowedPermissionGroups 中。如果是,它会获取该类型中所有的字符串常量字段,并将它们按字母顺序排序,最终将结果存储在一个字典中,字典的键是权限组的名称,值是该组中的权限列表。
代码中定义了三个 ConcurrentDictionary<string, string>,分别用于存储授权状态、令牌状态和令牌类型的描述。这些字典在静态构造函数中被初始化,提供了英文状态的中文翻译。
代码提供了三个公共方法,用于根据给定的键获取相应的描述:
"-"。GetTokenStatusDescription,但用于令牌类型。代码中定义了一个扩展方法,用于 ClaimsPrincipal 类型。这个扩展方法提供了一个属性 NameIdentifier,用于获取用户的 ID(即 ClaimTypes.NameIdentifier 的值)。如果没有找到该声明,则返回 null。
整体而言,这段代码的功能是提供一个帮助类,用于处理与身份验证和授权相关的操作,包括获取权限组、描述授权状态、令牌状态和令牌类型的中文翻译,以及扩展 ClaimsPrincipal 以获取用户 ID。它利用了反射、并发字典和延迟加载等技术来提高性能和可维护性。
