验证服务描述符出错:无法解析IHttpContextAccessor服务
问题分析与修复方案
问题根源
错误提示明确说明:DI容器无法解析Microsoft.AspNetCore.Http.IHttpContextAccessor类型的服务,导致无法激活ApiPortal.Classes.PolicyAuthorizationHandler。这是因为ASP.NET Core默认不会自动注册IHttpContextAccessor服务,必须手动添加注册逻辑。
修复步骤
1. 注册IHttpContextAccessor服务
在Startup.cs的ConfigureServices方法中,添加一行代码注册IHttpContextAccessor,建议放在授权处理器注册之前:
public void ConfigureServices(IServiceCollection services) { // ... 其他已有的服务注册代码 ... // 新增这行,注册IHttpContextAccessor services.AddHttpContextAccessor(); services.AddScoped<IAuthorizationHandler, PolicyAuthorizationHandler>(); // ... 后续服务注册代码 ... }
2. 优化PolicyRequirement代码(可选但推荐)
你的PolicyRequirement类中把传入的context和contextAccessor保存为字段是不必要的,且异步场景下可能存在线程安全问题,直接使用方法参数即可:
public class PolicyRequirement : IAuthorizationRequirement { public async Task<bool> Pass(AuthorizationHandlerContext context, IHttpContextAccessor contextAccessor, string area, string controller, string action, string id) { bool authorized = false; // 授权逻辑 string email = contextAccessor.HttpContext.User.Identity.Name; if (email == "myemail@email.com") authorized = true; return await Task.FromResult(authorized); } }
3. 简化授权处理器重复代码(可选)
PolicyAuthorizationHandler中的两个if块逻辑重复,可提取为公共方法精简代码:
public class PolicyAuthorizationHandler : AuthorizationHandler<PolicyRequirement> { readonly IHttpContextAccessor _contextAccessor; public PolicyAuthorizationHandler(IHttpContextAccessor ca) { _contextAccessor = ca; } protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PolicyRequirement requirement) { if (TryExtractRouteInfo(context.Resource, out var area, out var controller, out var action)) { if (await requirement.Pass(context, _contextAccessor, area, controller, action, "")) { context.Succeed(requirement); } } } private bool TryExtractRouteInfo(object resource, out string area, out string controller, out string action) { area = ""; controller = ""; action = ""; if (resource is AuthorizationFilterContext filterContext) { controller = (filterContext.RouteData.Values["controller"] as string)?.ToLower(); action = (filterContext.RouteData.Values["action"] as string)?.ToLower(); return true; } else if (resource is DefaultHttpContext httpContext) { controller = httpContext.Request.RouteValues["controller"]?.ToString(); action = httpContext.Request.RouteValues["action"]?.ToString(); return true; } return false; } }
内容的提问来源于stack exchange,提问作者Danny Verdel
相关产品推荐
相关产品推荐

