究竟什么'UseAuthentication()'用于?

bau*_*arb 27 c# authentication asp.net-core-middleware asp.net-core-2.0

我有一个关于ASP.NET Core 2中的身份验证的问题:调用app.UseAuthentication()究竟是什么?

这是一个基本的先决条件,以便我可以实现我的自定义身份验证逻辑吗?我已经看过UseAuthentication的实现以及实际的中间件AuthenticationMiddleware的实现,但说实话,我不明白它实际上在做什么以及为什么它是必要的.

换句话说:

我是否需要调用UseAuthentication() 在此输入图像描述

或者它是一个很好的,我可以做我的自定义auth反正? 在此输入图像描述

如果我没有调用UseAuthentication()就好了,我仍然对AuthenticationMiddleware实际上正在做什么感兴趣.所以,如果你知道如果你能为我解释,我会非常感激.

Mic*_*erg 16

虽然这是一个旧线程,但由于我最近偶然发现了同样的问题,我认为更多地了解内部结构可能会使其他人受益

简短的回答取决于您的服务类型和 API。你并不需要调用UseAuthentication时:

  1. 您实现自己的处理身份验证的中间件 - 无需在此详细说明。你自己处理一切,显然不需要额外的依赖
  2. 您不需要自动远程身份验证

远程认证

需要重定向到身份提供者的身份验证,例如 OpenID Connect。

是什么让它如此特别?

这些中间件需要关联不同的 http 调用。

初始调用首先由中间件处理,然后重定向到身份提供者(用户需要登录的位置),然后返回到中间件。在这种情况下,中间件需要拥有请求并且不允许其他身份验证中间件参与该过程。

这是中间件代码的第一部分:

// 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;
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 这当然是一个简化的解释,因为远程处理程序更复杂。目标最终是关注和解释中间件的行为

自动认证

为默认方案自动运行的身份验证。顾名思义,如果您定义了默认身份验证方案,那么与中间件关联的身份验证处理程序将始终运行。

直觉上,您会期望身份验证中间件首先运行,特别是它们应该在 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;
        }
}
Run Code Online (Sandbox Code Playgroud)

如果您正在开发支持多种身份验证方案或混合使用经过身份验证和未经身份验证的控制器的 REST API,那么您不需要自动身份验证,因为它增加了冗余。

结论

这给我们带来了一个有趣的问题和答案:身份验证不是自动的也不是远程的,何时何地发生?

在正常的 MVC 授权流程中,这发生在调用IAuthenticationService.AuthenticateAsync的 AuthorizeFilter 类中

  • 如果您实现自己的授权层或使用较低级别的 API(例如未实现为控制器的 websockets),您可以自己调用此方法

对于这些情况,UseAuthentication不需要调用


Mét*_*ule 12

如果您编写自定义中间件(就像您在示例中所做的那样),则无需调用,AddAuthentication因为身份验证中间件不会识别您自己的中间件.

话虽这么说,您可能不想创建自己的中间件:您可能希望创建一个与ASP.NET身份验证框架很好地配合的新身份验证处理程序(以便您[Authorize]在控制器上使用该属性).

要创建自定义身份验证,您必须创建一个继承自AuthenticationHandler并实现相关方法的专用处理程序.您可以在github上查看基本身份验证的示例:https://github.com/blowdart/idunno.Authentication,但这里是一个快速示例,用于显示自定义处理程序的要点.

public class BasicAuthenticationOptions : AuthenticationSchemeOptions
{
    public BasicAuthenticationOptions()
    {
    }
}

internal class BasicAuthenticationHandler : AuthenticationHandler<BasicAuthenticationOptions>
{
    private const string _Scheme = "MyScheme";

    public BasicAuthenticationHandler(
        IOptionsMonitor<BasicAuthenticationOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder,
        ISystemClock clock) : base(options, logger, encoder, clock)
    {
    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        string authorizationHeader = Request.Headers["Custom-Auth-Handler"];

        // create a ClaimsPrincipal from your header
        var claims = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, "My Name")
        };

        var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, Scheme.Name));
        var ticket = new AuthenticationTicket(claimsPrincipal,
            new AuthenticationProperties { IsPersistent = false },
            Scheme.Name
        );

        return AuthenticateResult.Success(ticket);
    }
Run Code Online (Sandbox Code Playgroud)

然后,您可以在Startup.cs以下位置注册新计划:

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
        .AddScheme<BasicAuthenticationOptions, BasicAuthenticationHandler>("MyScheme", options => { /* configure options */ })
}
Run Code Online (Sandbox Code Playgroud)

  • 此答案指的是[`AddAuthentication`](https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.extensions.dependencyinjection.authenticationservicecollectionextensions.addauthentication),但是OP正在询问[`UseAuthentication`]。 (https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.builder.authappbuilderextensions.useauthentication)。“ AddAuthentication”将auth服务添加到服务集合中,而“ UseAuthentication”将.NET Core的身份验证中间件添加到管道中。如果您有自己的自定义中间件,则不需要`UseAuthentication`。 (2认同)