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

Blazor Server脚手架身份认证无需EF Core对接Active Directory配置问题

问题原因

你遇到的报错本质是默认AddDefaultIdentity依赖IUserStore<IdentityUser>接口的实现,默认的EF Core存储实现由AddEntityFrameworkStores注入,你移除该方法后没有提供替代的存储实现,就会出现服务无法构造的错误。
你可以根据你的需求选择以下两种方案解决:

方案一:保留Identity SignInManager 用法,替换无数据库的自定义存储

如果你想继续使用脚手架生成的登录页原有逻辑,只需要自行实现一个轻量化的IUserStore<IdentityUser>,不需要对接数据库,仅实现登录必需的方法即可:

  1. 新增自定义用户存储类
public class CustomUserStore : IUserStore<IdentityUser>
{
    // 实现登录必需的用户查询方法
    public Task<IdentityUser> FindByIdAsync(string userId, CancellationToken cancellationToken)
    {
        return Task.FromResult(new IdentityUser(userId) { Id = userId });
    }

    public Task<IdentityUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
    {
        return Task.FromResult(new IdentityUser(normalizedUserName.Normalize()) { 
            Id = normalizedUserName,
            UserName = normalizedUserName 
        });
    }

    // 其余未用到的接口方法可以直接抛出未实现异常,运行时未调用就不会报错
    public Task<string> GetUserIdAsync(IdentityUser user, CancellationToken cancellationToken) => Task.FromResult(user.Id);
    public Task<string> GetUserNameAsync(IdentityUser user, CancellationToken cancellationToken) => Task.FromResult(user.UserName);
    public Task SetUserNameAsync(IdentityUser user, string userName, CancellationToken cancellationToken) => throw new NotImplementedException();
    public Task<string> GetNormalizedUserNameAsync(IdentityUser user, CancellationToken cancellationToken) => Task.FromResult(user.NormalizedUserName);
    public Task SetNormalizedUserNameAsync(IdentityUser user, string normalizedName, CancellationToken cancellationToken) => throw new NotImplementedException();
    public Task<IdentityResult> CreateAsync(IdentityUser user, CancellationToken cancellationToken) => throw new NotImplementedException();
    public Task<IdentityResult> UpdateAsync(IdentityUser user, CancellationToken cancellationToken) => throw new NotImplementedException();
    public Task<IdentityResult> DeleteAsync(IdentityUser user, CancellationToken cancellationToken) => throw new NotImplementedException();
    public void Dispose() { }
}
  1. 修改服务注册配置
    将原来的Identity注册代码替换为以下内容,用自定义存储替换EF Core存储:
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false)
    .AddUserStore<CustomUserStore>();

修改完成后你原来写的_signInManager.SignInAsync逻辑就可以正常运行,不会再触发EF Core数据库连接。

方案二:绕过Identity存储依赖,直接使用Cookie认证

如果你不需要Identity的全套用户管理功能,仅需要AD校验后登录,更推荐直接使用原生Cookie认证,逻辑更简单,完全无EF Core依赖:

  1. 替换服务注册配置
    删除原来的AddDefaultIdentity相关代码,改为注册Cookie认证服务:
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        // 可根据需求调整Cookie过期策略等配置
    });
builder.Services.AddAuthorization();
// 注意Blazor Server还要保留app.UseAuthentication()、app.UseAuthorization()中间件配置
  1. 修改登录页逻辑
    删掉Login.cshtml.cs中注入的SignInManager、UserManager,替换为自己的AD校验+Cookie登录逻辑:
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl ??= Url.Content("~/");
    if (ModelState.IsValid)
    {
        // 此处插入你自己的AD校验逻辑,校验用户名密码有效性
        bool adValidationPassed = ValidateADAccount(Input.UserName, Input.Password);
        if (adValidationPassed)
        {
            // 构造用户声明,可根据AD返回的信息补充角色、邮箱等自定义声明
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, Input.UserName)
            };
            var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
            // 执行登录
            await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme, 
                new ClaimsPrincipal(identity), 
                new AuthenticationProperties
                {
                    IsPersistent = Input.RememberMe,
                    ExpiresUtc = Input.RememberMe ? DateTimeOffset.UtcNow.AddDays(7) : null
                });
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        ModelState.AddModelError(string.Empty, "用户名或密码错误");
    }
    // 校验失败重新返回登录页
    ExternalLogins = (await HttpContext.GetAuthenticationSchemesAsync())
        .Where(x => x.DisplayName != null).ToList();
    return Page();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:27:03