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
相关产品推荐
相关产品推荐

