You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在ASP.NET Core Blazor Server登录时为用户添加Identity声明

编辑2:

最终已解决,可查看下方已接受答案。

编辑:

按照@Jason Pan的指导,我已上传完整的尝试代码。
我在登录过程中添加了声明(位于Login.cshtml.cs文件),并尝试从Razor组件中访问这些声明。
遗憾的是,此尝试未成功,我获取到的声明值始终为null。😔


原始问题

我已查阅过一些类似问题,但它们对我的场景并无帮助。

我的项目是一个Blazor Server应用,已按照官方步骤集成了Identity。

我希望实现以下需求:

  • 用户输入登录凭据。
  • 若用户名在Active Directory中有效,则从中获取EmployeeId字段。
  • 使用SignInManager.PasswordSignInAsync验证用户身份。
  • 将EmployeeId作为声明添加到ClaimsPrincipal中(以便我可以在Razor组件中通过级联参数的方式使用EmployeeId)。

我正纠结于如何在登录过程中将EmployeeId添加为声明。

我的Login.cshtml.cs中的OnPostAsync方法代码如下:

public class LoginModel : PageModel
{
    private readonly SignInManager<MMTUser> _signInManager;
    private readonly ILogger<LoginModel> _logger;

    public LoginModel(SignInManager<MMTUser> signInManager, ILogger<LoginModel> logger)
    {
        _signInManager = signInManager;
        _logger = logger;
    }

    [BindProperty]
    public InputModel Input { get; set; }

    public string ReturnUrl { get; set; }

    [TempData]
    public string ErrorMessage { get; set; }

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        returnUrl ??= Url.Content("~/");

        if (ModelState.IsValid)
        {
            // Step 1: Check if this user exists in our AD
            // If YES: Grab the Employee Id and go to next step
            // If NO: Terminate the process
            var adLookupResult = ADHelper.ADLookup(Input.Username);
            if (adLookupResult == null || string.IsNullOrEmpty(adLookupResult.EmployeeId))
            {
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                return Page();
            }

            // Step 2: SignIn the user
            var result = await _signInManager.PasswordSignInAsync(Input.Username, Input.Password, isPersistent: Input.RememberMe, lockoutOnFailure: false);

            // Step 3: How do I add adLookupResult.EmployeeId to the ClaimsPrincipal?

            if (result.Succeeded)
            {
                _logger.LogInformation("User logged in.");
                return LocalRedirect(returnUrl);
            }
            else
            {
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                return Page();
            }
        }

        // If we got this far, something failed, redisplay form
        return Page();
    }
    
    public class InputModel
    {
        [Required]
        public string Username { get; set; }

        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; }

        [Display(Name = "Remember me?")]
        public bool RememberMe { get; set; }
    }
}

解决方案

要在登录过程中动态添加EmployeeId声明,不能直接在PasswordSignInAsync之后修改ClaimsPrincipal,因为该方法已经完成了登录凭据的生成。正确的做法是手动生成用户主体,添加声明后再完成登录:

修改OnPostAsync方法中登录相关的代码段:

if (ModelState.IsValid)
{
    var adLookupResult = ADHelper.ADLookup(Input.Username);
    if (adLookupResult == null || string.IsNullOrEmpty(adLookupResult.EmployeeId))
    {
        ModelState.AddModelError(string.Empty, "登录尝试无效。");
        return Page();
    }

    // 先验证用户密码,不直接登录
    var user = await _signInManager.UserManager.FindByNameAsync(Input.Username);
    if (user == null || !await _signInManager.UserManager.CheckPasswordAsync(user, Input.Password))
    {
        ModelState.AddModelError(string.Empty, "登录尝试无效。");
        return Page();
    }

    // 生成用户主体并添加自定义声明
    var claimsPrincipal = await _signInManager.CreateUserPrincipalAsync(user);
    claimsPrincipal.Identities.First().AddClaim(new Claim("EmployeeId", adLookupResult.EmployeeId));

    // 手动完成登录
    await _signInManager.SignInAsync(user, Input.RememberMe);

    _logger.LogInformation("用户已登录。");
    return LocalRedirect(returnUrl);
}

关键说明:

  1. 替换PasswordSignInAsync为手动验证密码+生成主体的方式,这样才能在登录前修改ClaimsPrincipal。
  2. 使用CreateUserPrincipalAsync获取默认用户主体,在第一个身份标识中添加自定义声明。
  3. 调用SignInAsync完成登录,确保包含自定义声明的主体被持久化到Cookie中。

组件中访问声明的正确方式:

在Blazor组件中通过级联参数获取AuthenticationState,再提取声明:

@inject AuthenticationStateProvider AuthenticationStateProvider

@code {
    private string employeeId;

    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;
        employeeId = user.FindFirstValue("EmployeeId");
    }
}

内容的提问来源于stack exchange,提问作者Ash K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:10:43