用户在具有身份验证方案的策略中缺少标识



我创建了一个 ASP.NET Core 3.1应用程序,该应用程序使用2种身份验证类型 - cookie和JWT持有者。

我已经设置了一个方案,根据请求的路径将用户重定向到正确的方案:

.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = "smart";
sharedOptions.DefaultChallengeScheme = "smart";
})
.AddPolicyScheme("smart", "Bearer Authorization or Cookie", options =>
{
options.ForwardDefaultSelector = context =>
{
var requestPath = context.Request.Path;
if (CookiePolicyPathRegex.IsMatch(requestPath))
{
return CookieAuthenticationDefaults.AuthenticationScheme;
}
return JwtBearerDefaults.AuthenticationScheme;
};
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOAuthServiceScheme(Configuration); // Custom handler for JWT

我设置了授权策略,如下所示:

options.AddPolicy(ApiPolicies.CookiePolicy, policy =>
{
// policy.AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
policy.RequireRole(Roles.Access);
});
options.AddPolicy(ApiPolicies.JwtPolicy, policy =>
{
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
});

这工作正常,正在触发适当的策略,但我有一个问题。在我的集成测试中,我使用了一个中间件,该中间件为 cookie 身份验证添加了 ClaimIdentity:

public async Task Invoke(HttpContext context)
{
//  Removed for brevity
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
context.User = new ClaimsPrincipal(claimsIdentity);
await _next(context);
}

中间件设置为在身份验证中间件之前运行

ConfigureAdditionalMiddleware(app);
app.UseAuthentication();
app.UseAuthorization();

如果我从 cookie 策略中取消注释// policy.AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme);部分,则授权部分看不到在中间件中创建的身份。如果我留下评论,则标识就在那里,带有声明,身份验证类型和所有内容。如果我查看转发到两个身份验证方案的策略方案,则标识就在那里。

我的问题是,为什么添加CookieAuthenticationDefaults.AuthenticationScheme以某种方式隐藏使用相同身份验证类型创建的用户标识?

授权中间件将评估您的策略,并将运行将覆盖用户的身份验证逻辑。上下文

  • 在此处查看源代码 https://github.com/dotnet/aspnetcore/blob/6c7a8bb397de1fcfeeb6510ea39ef6eb02c15352/src/Security/Authorization/Policy/src/PolicyEvaluator.cs

以下是相关的代码片段(我删除并简化了代码以突出显示相关部分(:

public virtual async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
{
if (policy.AuthenticationSchemes != null && policy.AuthenticationSchemes.Count > 0)
{
var newPrincipal = await context.AuthenticateAsync(scheme).Principal;
if (newPrincipal != null)
{
context.User = newPrincipal;
return AuthenticateResult.Success(new AuthenticationTicket(newPrincipal, string.Join(";", policy.AuthenticationSchemes)));
}
else
{
context.User = new ClaimsPrincipal(new ClaimsIdentity());
return AuthenticateResult.NoResult();
}
}
...
}

因此,如您所见,当您为策略定义方案时,您输入"if"语句(这将设置一个新的context.User,如果您注释该行,身份验证逻辑将不会运行,您的自定义用户对象将在那里

最新更新