ASP.NET Core认证中匿名用户DI注入User类如何返回null?
ASP.NET Core 7中匿名请求时注入null到<User?>参数
场景与问题
在.NET 7的ASP.NET Core项目中,有一个同时允许认证用户和匿名用户访问的端点,需要根据用户认证状态执行不同逻辑。其他面向认证用户的服务中注入了作用域自定义类User,希望匿名场景下该类解析为null。
原实现代码:
// 生产环境中,非匿名用户会从数据库查询用户信息 builder.Services.AddScoped<User>(services => { if (User.IsAuthenticated()) return new User(/* ... */); else return null; }); // 端点注册 app.MapGet("/echo", (User? authedUser) => authedUser == null ? "Anonymous" : "Authed").RequireAuthorization().AllowAnonymous();
遇到的问题:DI工厂返回null符合预期,但匿名请求时DI抛出异常,提示未注册User实例——因为默认DI容器不允许注册的服务返回null。
解决方案
1. 注册IHttpContextAccessor获取请求上下文
要在DI工厂中判断用户认证状态,需先注册IHttpContextAccessor来访问当前请求的上下文信息:
builder.Services.AddHttpContextAccessor();
2. 注册可空类型User?而非User
将服务注册为可空引用类型,让DI容器允许返回null值:
builder.Services.AddScoped<User?>(services => { var httpContextAccessor = services.GetRequiredService<IHttpContextAccessor>(); var httpContext = httpContextAccessor.HttpContext; // 验证用户是否已认证 if (httpContext?.User?.Identity?.IsAuthenticated == true) { // 生产环境从数据库查询并返回用户实例 return new User(/* 填充用户信息 */); } // 匿名用户返回null return null; });
3. 调整端点参数与授权配置
端点参数保持User? authedUser,同时简化授权配置(AllowAnonymous已足够允许匿名访问,无需额外RequireAuthorization,除非有特定策略需求):
app.MapGet("/echo", (User? authedUser) => authedUser == null ? "Anonymous" : "Authed") .AllowAnonymous();
原理说明
ASP.NET Core DI容器默认要求注册的服务必须返回非null实例,除非注册的是可空引用类型(如User?)。当端点参数声明为User?时,DI会调用GetService<User?>而非GetRequiredService<User>,此时工厂返回null时容器会正常处理,不会抛出异常。
内容的提问来源于stack exchange,提问作者Dynalon
相关产品推荐
相关产品推荐

