网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
namespace Dpz.Core.Service.RepositoryServiceImpl;

/// <summary>
/// 用户安全服务实现
/// 提供用户SecurityStamp管理和安全相关功能
/// </summary>
public class UserSecurityService(
    IRepository<User> userRepository,
    ISecurityStampService securityStampService,
    ILogger<UserSecurityService> logger
) : IUserSecurityService
{
    /// <summary>
    /// 更新用户的SecurityStamp
    /// </summary>
    public async Task<string> UpdateUserSecurityStampAsync(
        string userId,
        string reason = "Security update"
    )
    {
        if (string.IsNullOrWhiteSpace(userId))
        {
            throw new ArgumentException("用户ID不能为空", nameof(userId));
        }

        try
        {
            // 生成新的SecurityStamp
            var newSecurityStamp = securityStampService.GenerateSecurityStamp();

            // 更新数据库
            var update = Builders<User>
                .Update.Set(x => x.Key, newSecurityStamp)
                .Set(x => x.LastUpdateTime, DateTime.Now);

            var result = await userRepository.UpdateAsync(x => x.Id == userId, update);

            if (result.ModifiedCount > 0)
            {
                logger.LogInformation(
                    "用户 {UserId} 的SecurityStamp已更新,原因:{Reason},新SecurityStamp:{SecurityStamp}",
                    userId,
                    reason,
                    newSecurityStamp
                );
                return newSecurityStamp;
            }

            logger.LogWarning("用户 {UserId} 的SecurityStamp更新失败,用户可能不存在", userId);
            throw new InvalidOperationException($"用户 {userId} 不存在或更新失败");
        }
        catch (Exception ex)
        {
            logger.LogError(
                ex,
                "更新用户 {UserId} 的SecurityStamp时发生错误,原因:{Reason}",
                userId,
                reason
            );
            throw;
        }
    }

    /// <summary>
    /// 验证用户的SecurityStamp是否有效(新方法,返回详细的验证结果)
    /// </summary>
    public async Task<UserSecurityValidationResult> ValidateUserSecurityStampDetailedAsync(
        string userId,
        string securityStamp
    )
    {
        if (string.IsNullOrWhiteSpace(userId) || string.IsNullOrWhiteSpace(securityStamp))
        {
            return UserSecurityValidationResult.SecurityStampInvalid;
        }

        try
        {
            // 首先验证SecurityStamp格式
            if (!securityStampService.IsValidSecurityStamp(securityStamp))
            {
                return UserSecurityValidationResult.SecurityStampInvalid;
            }

            // 从数据库获取用户的当前SecurityStamp和启用状态
            var user = await userRepository
                .Collection.Find(x => x.Id == userId)
                .Project(x => new { x.Key, x.Enable })
                .FirstOrDefaultAsync();

            if (user == null)
            {
                return UserSecurityValidationResult.UserNotFound;
            }

            if (user.Enable == false)
            {
                return UserSecurityValidationResult.UserDisabled;
            }

            if (user.Key != securityStamp)
            {
                return UserSecurityValidationResult.SecurityStampInvalid;
            }

            return UserSecurityValidationResult.Valid;
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "验证用户 {UserId} 的SecurityStamp时发生错误", userId);
            return UserSecurityValidationResult.SecurityStampInvalid;
        }
    }

    /// <summary>
    /// 验证用户的SecurityStamp是否有效
    /// </summary>
    public async Task<bool> ValidateUserSecurityStampAsync(string userId, string securityStamp)
    {
        if (string.IsNullOrWhiteSpace(userId) || string.IsNullOrWhiteSpace(securityStamp))
        {
            return false;
        }

        try
        {
            // 首先验证SecurityStamp格式
            if (!securityStampService.IsValidSecurityStamp(securityStamp))
            {
                return false;
            }

            // 从数据库获取用户的当前SecurityStamp
            var user = await userRepository
                .Collection.Find(x => x.Id == userId)
                .Project(x => new { x.Key, x.Enable })
                .FirstOrDefaultAsync();

            return user != null && user.Enable != false && user.Key == securityStamp;
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "验证用户 {UserId} 的SecurityStamp时发生错误", userId);
            return false;
        }
    }

    /// <summary>
    /// 强制用户重新登录
    /// </summary>
    public async Task<bool> ForceUserReauthenticationAsync(
        string userId,
        string reason = "Security enforcement"
    )
    {
        try
        {
            await UpdateUserSecurityStampAsync(userId, $"强制重新认证:{reason}");
            logger.LogInformation(
                "用户 {UserId} 被强制要求重新登录,原因:{Reason}",
                userId,
                reason
            );
            return true;
        }
        catch (Exception ex)
        {
            logger.LogError(
                ex,
                "强制用户 {UserId} 重新登录时发生错误,原因:{Reason}",
                userId,
                reason
            );
            return false;
        }
    }

    /// <summary>
    /// 批量更新多个用户的SecurityStamp
    /// </summary>
    public async Task<int> BatchUpdateSecurityStampsAsync(
        List<string> userIds,
        string reason = "Batch security update"
    )
    {
        if (userIds.Count == 0)
        {
            return 0;
        }

        var userIdList = userIds.ToList();
        var successCount = 0;

        logger.LogInformation(
            "开始批量更新 {Count} 个用户的SecurityStamp,原因:{Reason}",
            userIdList.Count,
            reason
        );

        foreach (var userId in userIdList)
        {
            try
            {
                await UpdateUserSecurityStampAsync(userId, reason);
                successCount++;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "批量更新用户 {UserId} 的SecurityStamp失败", userId);
                // 继续处理其他用户,不中断批量操作
            }
        }

        logger.LogInformation(
            "批量更新SecurityStamp完成,成功:{SuccessCount}/{TotalCount},原因:{Reason}",
            successCount,
            userIdList.Count,
            reason
        );

        return successCount;
    }

    /// <summary>
    /// 在密码修改时更新用户的SecurityStamp
    /// </summary>
    public async Task<string> UpdateSecurityStampOnPasswordChangeAsync(string userId)
    {
        return await UpdateUserSecurityStampAsync(userId, "密码修改");
    }
}

/// <summary>
/// 用户安全服务的扩展方法
/// </summary>
public static class UserSecurityServiceExtensions
{
    /// <summary>
    /// 在密码修改时更新SecurityStamp
    /// </summary>
    public static async Task<string> UpdateSecurityStampOnPasswordChangeAsync(
        this IUserSecurityService service,
        string userId
    )
    {
        return await service.UpdateUserSecurityStampAsync(userId, "密码修改");
    }

    /// <summary>
    /// 在账户被锁定时更新SecurityStamp
    /// </summary>
    public static async Task<bool> UpdateSecurityStampOnAccountLockAsync(
        this IUserSecurityService service,
        string userId
    )
    {
        return await service.ForceUserReauthenticationAsync(userId, "账户被锁定");
    }

    /// <summary>
    /// 在权限变更时更新SecurityStamp
    /// </summary>
    public static async Task<bool> UpdateSecurityStampOnPermissionChangeAsync(
        this IUserSecurityService service,
        string userId
    )
    {
        return await service.ForceUserReauthenticationAsync(userId, "权限变更");
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码实现了一个用户安全服务 (UserSecurityService),主要用于管理用户的安全标识(SecurityStamp)以及与安全相关的功能。以下是代码的主要功能和结构的详细解释:

1. 类和接口

  • UserSecurityService: 这是一个实现了 IUserSecurityService 接口的类,负责用户安全相关的操作。
  • 构造函数: 接受三个参数:
    • IRepository<User> userRepository: 用于与用户数据进行交互的仓储接口。
    • ISecurityStampService securityStampService: 用于生成和验证安全标识的服务。
    • ILogger<UserSecurityService> logger: 用于记录日志的接口。

2. 方法

2.1 UpdateUserSecurityStampAsync

  • 功能: 更新指定用户的安全标识(SecurityStamp)。
  • 参数:
    • userId: 用户的唯一标识。
    • reason: 更新的原因,默认为 "Security update"。
  • 逻辑:
    • 验证 userId 是否为空。
    • 生成新的安全标识。
    • 更新数据库中的用户记录。
    • 记录更新成功或失败的日志。

2.2 ValidateUserSecurityStampAsync

  • 功能: 验证用户的安全标识是否有效。
  • 参数:
    • userId: 用户的唯一标识。
    • securityStamp: 要验证的安全标识。
  • 逻辑:
    • 验证输入参数是否为空。
    • 检查安全标识的格式是否有效。
    • 从数据库中获取用户的当前安全标识并进行比较。

2.3 ForceUserReauthenticationAsync

  • 功能: 强制用户重新认证。
  • 参数:
    • userId: 用户的唯一标识。
    • reason: 强制重新认证的原因,默认为 "Security enforcement"。
  • 逻辑:
    • 调用 UpdateUserSecurityStampAsync 方法更新安全标识。
    • 记录强制重新认证的日志。

2.4 BatchUpdateSecurityStampsAsync

  • 功能: 批量更新多个用户的安全标识。
  • 参数:
    • userIds: 用户ID的列表。
    • reason: 批量更新的原因,默认为 "Batch security update"。
  • 逻辑:
    • 验证用户ID列表是否为空。
    • 遍历用户ID列表,逐个更新安全标识,并记录成功和失败的日志。

2.5 UpdateSecurityStampOnPasswordChangeAsync

  • 功能: 在用户密码修改时更新安全标识。
  • 参数:
    • userId: 用户的唯一标识。
  • 逻辑:
    • 调用 UpdateUserSecurityStampAsync 方法,原因设置为 "密码修改"。

3. 扩展方法

  • UserSecurityServiceExtensions: 提供了一些扩展方法,方便在特定情况下更新安全标识。
    • UpdateSecurityStampOnPasswordChangeAsync: 在密码修改时更新安全标识。
    • UpdateSecurityStampOnAccountLockAsync: 在账户被锁定时强制用户重新认证。
    • UpdateSecurityStampOnPermissionChangeAsync: 在权限变更时强制用户重新认证。

总结

整体而言,这段代码提供了一套完整的用户安全管理功能,主要用于更新和验证用户的安全标识,确保用户的安全性。通过日志记录,开发人员可以追踪安全相关的操作和事件。

loading