虽然这是一个旧的线程,但由于我最近遇到了同样的问题,我认为在内部方面提供更多光芒可能有益于其他人
简短的答案是取决于您的服务类型和API。当:
- 您实现自己的中间件来处理身份验证时-无需在此展开。您自己处理所有内容,显然不需要额外的依赖项
- 您不需要自动或远程身份验证
远程身份验证
需要重定向到标识提供商(如OpenID Connect)的身份验证。
有什么特别之处?
这些中间件需要关联不同的http调用。
首先,中间件处理初始调用,然后将其重定向到标识提供程序(用户需要登录),然后返回到中间件。
在这种情况下,中间件需要拥有请求,并且不允许其他身份验证中间件参与该过程。
这是中间件代码的第一部分:
middleware// Give any IAuthenticationRequestHandler schemes a chance to handle the request
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;
}
}
- 当然,这只是一个简化的解释,远程处理程序更加复杂。最终的目标是专注并解释中间件的行为。
自动身份验证
默认方案下自动运行的身份验证。正如其名称所示,如果您定义了默认身份验证方案,则与中间件关联的身份验证处理程序将始终运行。
直观上,您会期望身份验证中间件首先运行,特别是它们应该在MVC层(即控制器)之前运行。但是,这也意味着身份验证层不知道哪些控制器应该运行或这些控制器的授权要求,换句话说,它不知道需要评估的授权策略[Authorize("Policy")]
是什么。
因此,逻辑上,我们希望首先评估策略,然后再运行身份验证逻辑。这就是为什么身份验证处理程序在ASP 2.*中转移到通用服务而不是耦合到中间件中的原因。
但是,在某些情况下,您始终希望运行身份验证处理程序,而不管您的策略如何。在这种情况下,您可以定义默认身份验证方案,这些方案将自动运行。
这解释了中间件代码的第二部分:
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
if (result?.Principal != null)
{
context.User = result.Principal;
}
}
如果您正在开发支持多个身份验证方案或具有经过身份验证和非身份验证控制器混合的REST API,则不需要自动身份验证,因为它会增加冗余。
结论
这带来了一个有趣的问题和答案:当身份验证不是自动的且不是远程时,何时何地进行身份验证?
在正常的MVC授权流程中,这发生在AuthorizeFilter类中,该类调用IAuthenticationService.AuthenticateAsync
- 如果实现自己的授权层或使用较低级别的API(例如未实现为控制器的WebSockets)时,可以自己调用此方法。
对于这些情况,不需要调用UseAuthentication