网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using Dpz.Core.EnumLibrary;
using Dpz.Core.Service.RepositoryService;
using Microsoft.AspNetCore.Authentication;

namespace Dpz.Core.Auth.Middleware;

/// <summary>
/// SecurityStamp验证中间件
/// 用于在密码修改后自动登出其他浏览器的会话
/// </summary>
public class SecurityStampValidationMiddleware(
    RequestDelegate next,
    ILogger<SecurityStampValidationMiddleware> logger
)
{
    public async Task InvokeAsync(HttpContext context, IUserSecurityService userSecurityService)
    {
        // 只对已认证的用户进行验证
        if (context.User.Identity?.IsAuthenticated == true)
        {
            var account = context.User.NameIdentifier;
            var claimKey = context.User.FindFirst("Key")?.Value;

            if (!string.IsNullOrEmpty(account) && !string.IsNullOrEmpty(claimKey))
            {
                try
                {
                    // 使用新的UserSecurityService验证SecurityStamp,获取详细的验证结果
                    var validationResult =
                        await userSecurityService.ValidateUserSecurityStampDetailedAsync(
                            account,
                            claimKey
                        );

                    // 根据不同的验证结果进行处理
                    if (validationResult != UserSecurityValidationResult.Valid)
                    {
                        logger.LogInformation(
                            "用户 {Account} 的验证失败,原因:{Reason}",
                            account,
                            validationResult
                        );

                        // 登出用户
                        await context.SignOutAsync();

                        // 根据不同的失败原因,重定向到不同的错误页面
                        var redirectUrl = validationResult switch
                        {
                            UserSecurityValidationResult.UserDisabled =>
                                "/sign-in?msg=account-disabled",
                            UserSecurityValidationResult.SecurityStampInvalid =>
                                "/sign-in?msg=security-stamp-expired",
                            UserSecurityValidationResult.UserNotFound =>
                                "/sign-in?msg=user-not-found",
                            _ => "/sign-in?msg=auth-error",
                        };

                        context.Response.Redirect(redirectUrl);
                        return;
                    }
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, "验证用户 {Account} 的SecurityStamp时发生错误", account);
                }
            }
        }

        await next(context);
    }
}

/// <summary>
/// SecurityStamp验证中间件扩展方法
/// </summary>
public static class SecurityStampValidationMiddlewareExtensions
{
    public static IApplicationBuilder UseSecurityStampValidation(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<SecurityStampValidationMiddleware>();
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码实现了一个名为 SecurityStampValidationMiddleware 的中间件,用于在 ASP.NET Core 应用程序中验证用户的安全戳(Security Stamp)。其主要功能是确保在用户密码被修改或账户安全状态发生变化时,自动登出其他会话。这是为了增强安全性,防止未授权的访问。

代码功能详解

  1. 中间件构造函数:

    • SecurityStampValidationMiddleware 类的构造函数接受一个 RequestDelegate 和一个 ILogger 实例。RequestDelegate 用于调用下一个中间件,ILogger 用于记录日志。
  2. InvokeAsync 方法:

    • 这是中间件的核心方法,处理传入的 HTTP 请求。
    • 首先,它检查当前用户是否已认证(context.User.Identity?.IsAuthenticated)。
    • 如果用户已认证,获取用户的标识(account)和安全戳(claimKey)的值。
  3. 安全戳验证:

    • 如果 accountclaimKey 都不为空,调用 IUserSecurityServiceValidateUserSecurityStampAsync 方法来验证安全戳。
    • 如果验证失败(即安全戳无效),这意味着用户的密码可能已被修改,或者账户的安全状态发生了变化。
  4. 登出操作:

    • 在安全戳无效的情况下,记录一条信息日志,指明用户的安全戳已过期。
    • 调用 context.SignOutAsync() 方法登出用户。
    • 然后重定向用户到登录页面,并附加一个消息参数(msg=security-stamp-expired),提示用户安全戳已过期。
  5. 异常处理:

    • 在验证过程中,如果发生异常,捕获并记录错误信息。
  6. 中间件扩展方法:

    • SecurityStampValidationMiddlewareExtensions 类提供了一个扩展方法 UseSecurityStampValidation,用于将中间件添加到 ASP.NET Core 的请求处理管道中。

总结

这个中间件的主要目的是在用户的安全戳失效时,自动登出用户并引导他们重新登录,从而提高应用程序的安全性。它确保了用户在密码更改后不会继续保持登录状态,防止潜在的安全风险。

loading