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

ASP.NET Web API静态Main内实例化UserContext验证账号密码报错

解决ASP.NET Web API中idunno.Authentication.Basic结合EF Core的认证实例化错误

问题场景

在ASP.NET Web API中使用idunno.Authentication.Basic实现认证功能,核心需求是将用户输入的账号密码与数据库AuthUsers表进行比对验证。但在静态Main方法中尝试实例化UserContext时触发类型转换错误,无法正常完成数据库验证。

错误信息

Severity Code Description Project File Line Suppression State
cannot convert from 'Microsoft.Extensions.DependencyInjection.IServiceCollection' to 'Microsoft.EntityFrameworkCore.DbContextOptions<minimalAPI.models.UserContext>'

原有代码

Program.cs

public static void Main(string[] args)
{
    var builder = WebApplication.CreateBuilder(args);

    // Add services to the container.
    builder.Services.AddDbContext<UserContext>(options =>
        options.UseSqlServer(builder.Configuration.GetConnectionString("MinimalAPIDatabase")));

    //uses idunno.Authentication.Basic
    builder.Services.AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
        .AddBasic(options =>
        {
            options.Realm = "Basic Authentication";
            options.Events = new BasicAuthenticationEvents
            {
                OnValidateCredentials = async context =>
                {
                    string username = context.Username;
                    string password = context.Password;

                    var options = builder.Services.ConfigureOptions(null);
                    
                    UserContext _userContext = new UserContext(options);

                    AuthUser? user = await _userContext.AuthUsers.FirstOrDefaultAsync(u => u.UserName == username && u.Password == password);

                    if (user != null)
                        if (user != null)
                        {
                            var claims = new[]
                            {
                                new Claim(ClaimTypes.NameIdentifier, context.Username, ClaimValueTypes.String, context.Options.ClaimsIssuer),
                                new Claim(ClaimTypes.Name, context.Username, ClaimValueTypes.String, context.Options.ClaimsIssuer)
                            };

                            context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
                            context.Success();
                        }

                    return Task.CompletedTask;
                }
            };
        });
}

UserContext.cs

public class UserContext : DbContext
{       
    public UserContext(DbContextOptions<UserContext> options) : base(options)
    {
      
    }

    public DbSet<User> Users { get; set; }
    public DbSet<AuthUser> AuthUsers { get; set; }
}

解决方案

错误根源是手动实例化UserContext的方式错误,应该从依赖注入容器获取已注册的服务实例,而非自行构造。具体修改如下:

修正后的Program.cs代码

public static void Main(string[] args)
{
    var builder = WebApplication.CreateBuilder(args);

    // 注册UserContext到依赖注入容器
    builder.Services.AddDbContext<UserContext>(options =>
        options.UseSqlServer(builder.Configuration.GetConnectionString("MinimalAPIDatabase")));

    // 配置Basic认证
    builder.Services.AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
        .AddBasic(options =>
        {
            options.Realm = "Basic Authentication";
            options.Events = new BasicAuthenticationEvents
            {
                OnValidateCredentials = async context =>
                {
                    string username = context.Username;
                    string password = context.Password;

                    // 从HttpContext的服务容器中获取UserContext实例
                    var userContext = context.HttpContext.RequestServices.GetRequiredService<UserContext>();

                    // 查询数据库验证账号密码
                    AuthUser? user = await userContext.AuthUsers
                        .FirstOrDefaultAsync(u => u.UserName == username && u.Password == password);

                    if (user != null)
                    {
                        var claims = new[]
                        {
                            new Claim(ClaimTypes.NameIdentifier, username, ClaimValueTypes.String, context.Options.ClaimsIssuer),
                            new Claim(ClaimTypes.Name, username, ClaimValueTypes.String, context.Options.ClaimsIssuer)
                        };

                        context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
                        context.Success();
                    }

                    return Task.CompletedTask;
                }
            };
        });

    // 添加授权服务
    builder.Services.AddAuthorization();

    var app = builder.Build();

    // 启用认证和授权中间件(顺序不能错)
    app.UseAuthentication();
    app.UseAuthorization();

    // 配置API路由等逻辑
    app.MapControllers();

    app.Run();
}

额外优化建议

  • 密码安全:禁止明文存储密码,建议使用ASP.NET Core自带的PasswordHasher<T>或第三方库(如BCrypt)对密码进行哈希处理,验证时对比哈希值而非明文。
  • 逻辑解耦:可将用户验证逻辑抽离为独立服务(如IAuthService),注入到认证事件中,降低代码耦合度,提升可维护性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:57:05