.net AuthenticationMiddleware如何处理多个方案

gg0vcinb  于 2023-11-20  发布在  .NET
关注(0)|答案(2)|浏览(164)

我们知道我们可以使用多种方案来验证用户,例如

  1. builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  2. .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme,
  3. options => builder.Configuration.Bind("JwtSettings", options))
  4. .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
  5. options => builder.Configuration.Bind("CookieSettings", options));

字符串
但是根据AuthenticationMiddleware代码:https://source.dot.net/#Microsoft.AspNetCore. Authentication/AuthenticationMiddleware.cs,50

  1. public async Task Invoke(HttpContext context)
  2. {
  3. // ...
  4. var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
  5. foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
  6. {
  7. var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler;
  8. if (handler != null && await handler.HandleRequestAsync())
  9. {
  10. return;
  11. }
  12. }
  13. var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
  14. if (defaultAuthenticate != null)
  15. {
  16. var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
  17. // ...
  18. }
  19. await _next(context);
  20. }


foreach似乎首先应用了多个方案。然而,它使用的是IAuthenticationRequestHandler而不是IAuthenticationHandler
因此,当我们调用AddCookie扩展方法时,我们将处理程序类型的scheme添加为CookieAuthenticationHandler(https://source.dot.net/#Microsoft.AspNetCore.Authentication. Cookies/CookieExtensions.cs,81),接口实现链为:

  1. public class CookieAuthenticationHandler : SignInAuthenticationHandler<CookieAuthenticationOptions>
  2. public abstract class SignInAuthenticationHandler<TOptions> : SignOutAuthenticationHandler<TOptions>, IAuthenticationSignInHandler
  3. // ...


SignInAuthenticationHandler没有实现IAuthenticationRequestHandler,如果我们一直向上追溯,那么AuthenticationMiddleware是如何处理多个方案并调用多个处理程序的呢?据我所知,只应用了默认方案?

daupos2t

daupos2t1#

AuthenticationMiddleware如何处理多个方案并调用多个处理程序?
不会的正如你提到的,AuthenticationMiddleware只对默认方案进行身份验证。如果你有多个身份验证方案,你需要使用AuthorizationMiddlewarePolicy。你可以设置策略必须使用的身份验证方案并将其应用于端点。然后AuthorizationMiddleware将使用指定的方案对该端点进行身份验证。

hyrbngr7

hyrbngr72#

**注意:**这个答案是基于我对ASP.NET Core 7.0.13的程序集和源代码的阅读-它不适用于ASP.NET Core的早期版本,如1.x,2.x和3.x(甚至可能是5.x甚至6.x),其中authX系统设计经历了频繁的重新设计和迭代。

在答复任择议定书的后续问题时:
好的,你能给我看看AuthenticationMiddleware源代码吗?哪个代码块调用了多个IAuthenticationHandler
答案是“它不会”(基本上是the same as what @Kahbazi says in his answer),但这必然会让我们问 “那么,当您指定多个身份验证方案时,[Authorize]是如何工作的?"..
.这个问题的答案在于 * 另一个中间件 *,因为(令人惊讶的是),AuthenticationMiddleware并不是唯一执行请求身份验证的中间件。

要点1:您将有一个隐式或显式的AuthorizationPolicy

当您有一个列出了多个方案的[Authorize]属性(如[Authorize( AuthenticationSchemes = "MyCookieScheme, MyJwtScheme, MyHttpBasicScheme" )])时,ASP.NET将隐式地将该属性转换为AuthorizationPolicy(通过interface IAuthorizeData),每个方案都列在该策略的.AuthenticationSchemes字符串集合中。
在另一种情况下,如果您直接专门配置AuthorizationPolicy(而不使用[Authorize]),那么您也可以在.AuthenticationSchemes中设置多个方案名称。

要点2:AuthorizationPolicy实际上是由不同的中间件进行评估的,而不是由AuthenticationMiddleware进行评估的

..
.所以反直觉,_当你使用2个或更多的身份验证方案,然后AuthorizationMiddleware将执行双重职责,也验证请求除了授权他们.
就在这里:https://github.com/dotnet/aspnetcore/blob/ae33890a62edb2fed5554efab597fb7fc41f8cbe/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs#L156C9-L156C9

  1. public class AuthorizationMiddleware
  2. {
  3. public async Task Invoke(HttpContext context)
  4. {
  5. // ...
  6. var policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>();
  7. var authenticateResult = await policyEvaluator.AuthenticateAsync(policy, context); // <-- In here
  8. // ...
  9. }

字符串
foreach循环遍历所有列出的AuthenticationSchemesis in class PolicyEvaluator : IPolicyEvaluator

  1. foreach (var scheme in policy.AuthenticationSchemes)
  2. {
  3. var result = await context.AuthenticateAsync(scheme);
  4. if (result != null && result.Succeeded)
  5. {
  6. // ...
  7. }
  8. }

展开查看全部

相关问题