ASP.NET 8中Windows身份验证结合自定义策略授权致HandleRequirementAsync调用两次
问题分析与解决方案
为什么授权处理器会被调用两次?
这是Negotiate(NTLM/Kerberos)认证的挑战-响应机制导致的:
- 第一次请求:客户端未携带认证凭证,服务器返回401挑战,此时授权流程会执行一次,但用户还未完成认证,所以
IsAuthenticated为false。 - 第二次请求:客户端收到401后,自动携带认证凭证发起请求,此时认证完成,授权流程再次执行,
IsAuthenticated为true。
这属于该认证方式的正常行为,并非代码bug。
优化方案:避免未认证时的无效授权调用
修改授权策略配置,强制要求用户先完成认证,再执行自定义授权逻辑:
builder.Services.AddAuthorization(options => { options.AddPolicy("CanGetWeather", policy => { policy.RequireAuthenticatedUser(); // 新增:仅允许已认证用户进入授权逻辑 policy.Requirements.Add(new CanGetWeatherRequirement()); }); });
这样只有当用户认证通过后,才会触发你的自定义授权处理器,避免第一次未认证时的无效调用。
另外,你的授权处理器代码有个潜在风险:context.User.Identities.First()可能会在用户无身份标识时抛出空引用异常,建议调整为:
protected override async Task HandleRequirementAsync( AuthorizationHandlerContext context, CanGetWeatherRequirement requirement ) { var identity = context.User.Identity; if (identity?.IsAuthenticated == true) { if (await UserCanGetWeatherAsync()) context.Succeed(requirement); } }
额外说明
如果使用Bearer Token这类认证方式,客户端会在第一次请求就携带认证凭证,不会出现两次授权调用的情况。而Negotiate认证依赖HTTP的挑战-响应流程,两次请求是其固有特性。
内容的提问来源于stack exchange,提问作者skomark
相关产品推荐
相关产品推荐

