虽然这是一个旧线程,但由于我最近偶然发现了同样的问题,我认为更多地了解内部原理可能会使其他人受益
简短的回答取决于您的服务类型和 API。您不需要在以下情况下需要致电UseAuthentication:
- 您实现自己的处理身份验证的中间件 - 无需在此详细说明。您自己处理所有事情,显然不需要额外的依赖项
- 您不需要自动或远程身份验证
远程认证
需要重定向到身份提供者的身份验证,例如 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.* 中移动为通用服务而不是与中间件耦合的原因。
但是,在某些情况下,您总是希望身份验证处理程序运行,而不管您的策略如何。在这种情况下,您可以定义将自动运行的默认身份验证方案。
这解释了middleware 代码的第二部分:
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 授权流程中,这发生在调用 IAuthenticationService.AuthenticateAsync 的 AuthorizeFilter 类中
- 如果您实现自己的授权层或使用较低级别的 API(例如未作为控制器实现的 websocket),您可以自己调用此方法
对于这些情况,不需要调用UseAuthentication