using System;
using System.Security.Claims;
using Dpz.Core.EnumLibrary;

namespace Dpz.Core.Infrastructure;

public static class UserExtensions
{
    extension(ClaimsPrincipal? principal)
    {
        /// <summary>
        /// 账号 用户ID
        /// </summary>
        public string? NameIdentifier => principal?.FindFirst(ClaimTypes.NameIdentifier)?.Value;

        /// <summary>
        /// 严格获取用户ID
        /// <exception cref="CurrentUserRequiredException">如果用户未登录,将会引发此异常</exception>
        /// </summary>
        public string RequiredNameIdentifier =>
            principal?.NameIdentifier ?? throw new CurrentUserRequiredException();

        /// <summary>
        /// SessionId
        /// </summary>
        public string? SessionId =>
            principal?.FindFirst(UserSessionKeys.SessionIdClaim)?.Value
            ?? principal?.FindFirst(UserSessionKeys.SessionIdProperty)?.Value;

        /// <summary>
        /// 权限
        /// </summary>
        public Permissions? Permissions => principal.ParsePermissions();

        /// <summary>
        /// 是否具有系统权限
        /// </summary>
        public bool HasSystem => principal.HasSystemPermission();

        private Permissions? ParsePermissions()
        {
            var permissionClaim = principal?.FindFirst("Permissions")?.Value;
            if (permissionClaim is null)
            {
                return null;
            }
            if (Enum.TryParse<Permissions>(permissionClaim, ignoreCase: true, out var permissions))
            {
                return permissions;
            }
            return null;
        }

        private bool HasSystemPermission()
        {
            var permissions = principal?.ParsePermissions();
            return permissions.HasValue
                && (permissions.Value & Permissions.System) == Permissions.System;
        }

        /// <summary>
        /// 是否已认证
        /// </summary>
        public bool Authenticated => principal?.Identity?.IsAuthenticated == true;
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

代码解释

这是一个使用 C# 扩展方法(Extension Methods)的代码文件,为 ClaimsPrincipal 类型添加了一系列便捷的用户身份信息访问方法。

主要功能

1. 扩展声明

extension(ClaimsPrincipal? principal)

这是 C# 的新语法(可能是 C# 10/11+ 的扩展类型特性),为 ClaimsPrincipal? 类型添加扩展成员。

2. 核心属性和方法

NameIdentifier (用户ID)

  • 从 Claims 中提取用户标识符
  • 使用标准的 ClaimTypes.NameIdentifier
  • 可为 null

RequiredNameIdentifier (严格用户ID)

  • 强制获取用户ID,如果不存在则抛出 CurrentUserRequiredException 异常
  • 用于必须有用户登录的场景

SessionId (会话ID)

  • 尝试从两个不同的 Claim 键中获取会话ID:
    • UserSessionKeys.SessionIdClaim
    • UserSessionKeys.SessionIdProperty
  • 使用 null 合并运算符提供备用查找

Permissions (权限)

  • 调用私有方法 ParsePermissions() 解析权限
  • 从 "Permissions" Claim 中读取并转换为 Permissions 枚举

HasSystem (是否有系统权限)

  • 调用 HasSystemPermission() 检查是否具有系统级权限
  • 使用位运算检查 Permissions.System 标志

Authenticated (是否已认证)

  • 检查用户是否已通过身份验证
  • 通过 Identity.IsAuthenticated 属性判断

3. 私有辅助方法

ParsePermissions()

private Permissions? ParsePermissions()
  • 从 Claims 中提取 "Permissions" 值
  • 尝试解析为 Permissions 枚举类型
  • 解析失败返回 null

HasSystemPermission()

private bool HasSystemPermission()
  • 使用位运算检查是否包含系统权限
  • (permissions.Value & Permissions.System) == Permissions.System 是标准的标志枚举检查方式

使用场景

这个扩展类通常用于:

  • ASP.NET Core 应用的用户身份验证和授权
  • 简化从 ClaimsPrincipal 中提取常用用户信息
  • 统一的权限检查逻辑

示例用法

// 在 Controller 或 Service 中
var userId = User.NameIdentifier;  // 可能为 null
var strictUserId = User.RequiredNameIdentifier;  // 不存在会抛异常
var hasSystemAccess = User.HasSystem;
if (User.Authenticated) { /* 已登录逻辑 */ }

依赖

  • Dpz.Core.EnumLibrary - 包含 Permissions 枚举定义
  • 自定义异常 CurrentUserRequiredException
  • UserSessionKeys 常量类

这是一个设计良好的辅助工具类,提高了用户身份信息访问的便利性和类型安全性。

评论加载中...