提问人:user22155685 提问时间:11/13/2023 更新时间:11/13/2023 访问量:68
AuthenticationMiddleware 如何处理多个方案
How does AuthenticationMiddleware handle multiple schemes
问:
我们知道我们可以使用多种方案来授权用户,例如
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme,
options => builder.Configuration.Bind("JwtSettings", options))
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
options => builder.Configuration.Bind("CookieSettings", options));
但根据代码:https://source.dot.net/#Microsoft.AspNetCore.Authentication/AuthenticationMiddleware.cs,50AuthenticationMiddleware
public async Task Invoke(HttpContext context)
{
// ...
var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
{
var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler;
if (handler != null && await handler.HandleRequestAsync())
{
return;
}
}
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
// ...
}
await _next(context);
}
似乎首先应用了多个方案。但是,它使用 not .foreach
IAuthenticationRequestHandler
IAuthenticationHandler
因此,当我们调用扩展方法时,我们将处理程序类型的方案添加为 (https://source.dot.net/#Microsoft.AspNetCore.Authentication.Cookies/CookieExtensions.cs,81)
接口实现链为:AddCookie
CookieAuthenticationHandler
public class CookieAuthenticationHandler : SignInAuthenticationHandler<CookieAuthenticationOptions>
public abstract class SignInAuthenticationHandler<TOptions> : SignOutAuthenticationHandler<TOptions>, IAuthenticationSignInHandler
// ...
SignInAuthenticationHandler
如果我们一直跟踪,则不会实现,那么如何处理多个方案并调用多个处理程序呢?据我所知,只应用了默认方案?IAuthenticationRequestHandler
AuthenticationMiddleware
答:
AuthenticationMiddleware 如何处理多个方案并调用多个处理程序?
不会的!如您所述,仅对默认方案进行身份验证。如果您有多个身份验证方案,则需要使用 和 。您可以设置策略必须使用的身份验证方案,并将其应用于终端节点。然后,将使用指定的方案对该端点进行身份验证。AuthenticationMiddleware
AuthorizationMiddleware
Policy
AuthorizationMiddleware
注意:这个答案是基于我对 ASP.NET Core 7.0.13 的程序集和源代码的阅读——它不适用于 ASP.NET Core 的早期版本,如 1.x、2.x 和 3.x(甚至可能是 5.x 甚至 6.x),其中 authX 系统设计经历了频繁的重新设计和迭代。
在评论中回应OP的后续问题:
好的,你能告诉我代码块调用多个的源代码吗
AuthenticationMiddleware
IAuthenticationHandler
答案是“它没有”(基本上,与@Kahbazi在他的回答中所说的相同),但这必然导致我们问“那么,当您指定多个身份验证方案时,[授权]
是如何工作的?...
...这个问题的答案在于另一个中间件,因为(令人惊讶的是),它并不是唯一执行请求身份验证的中间件。AuthenticationMiddleware
第 1 点:您将有一个隐式或显式:AuthorizationPolicy
当您的属性列出了多个方案时,ASP.NET 会将该属性隐式转换为 (via ),每个方案都列在该策略的字符串集合中。[Authorize]
[Authorize( AuthenticationSchemes = "MyCookieScheme, MyJwtScheme, MyHttpBasicScheme" )]
AuthorizationPolicy
interface IAuthorizeData
.AuthenticationSchemes
在另一种情况下,您专门配置了一个直接(不使用 ),那么您也可以在其中设置多个方案名称。AuthorizationPolicy
[Authorize]
.AuthenticationSchemes
第 2 点:实际上是由不同的中间件而不是由AuthorizationPolicy
AuthenticationMiddleware
...相反,它由 .AuthorizationMiddleware
...因此,与直觉相反,_when您使用 2 个或更多身份验证方案,那么除了授权请求外,它们还将执行双重任务并验证请求。AuthorizationMiddleware
public class AuthorizationMiddleware
{
public async Task Invoke(HttpContext context)
{
// ...
var policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>();
var authenticateResult = await policyEvaluator.AuthenticateAsync(policy, context); // <-- In here
// ...
}
遍历所有列出的循环位于 PolicyEvaluator 类中: IPolicyEvaluator:
foreach
AuthenticationSchemes
foreach (var scheme in policy.AuthenticationSchemes)
{
var result = await context.AuthenticateAsync(scheme);
if (result != null && result.Succeeded)
{
// ...
}
}
评论
IAuthenticationRequestHandler
[AuthorizeAttribute]
[Authorize]
AuthenticationMiddleware
IAuthenticationHandler