没有为方案“Identity.TwoFactorUserId”注册注销身份验证处理程序

Luk*_*ett 4 asp.net-core-2.0

ASP.NET Core 2.2 Web 应用程序使用从完整 MVC 应用程序迁移的代码。

我的路径AccountController包含这个简单的代码Logout

await this.SignInManager.SignOutAsync();
return this.RedirectToAction(nameof(Landing.HomeController.Index), "Home");
Run Code Online (Sandbox Code Playgroud)

但这给出了。

没有为方案“Identity.TwoFactorUserId”注册注销身份验证处理程序。

考虑到我从未在代码中提到过 2FA,而且 Google 登录正在工作,这非常令人困惑。

serviceCollection
    .AddIdentityCore<MyUser>(identityOptions =>
    {
        identityOptions.SignIn.RequireConfirmedEmail = false;
    })
    .AddUserStore<MyUserStore>()
    .AddSignInManager<SignInManager<MyUser>>();

serviceCollection.AddAuthentication(IdentityConstants.ApplicationScheme)
    .AddCookie(IdentityConstants.ApplicationScheme, options =>
    {
        options.SlidingExpiration = true;
    })
    .AddGoogle(googleOptions =>
    {
        this.Configuration.Bind("OAuth2:Providers:Google", googleOptions);

        googleOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
    })
    .AddExternalCookie();
Run Code Online (Sandbox Code Playgroud)

itm*_*nus 9

作为对@Luke答案的补充:

之所以抛出异常,是因为这个方法也会在后台SignInManager::SignOutAsync()注销:TwoFactorUserIdScheme

公共虚拟异步任务 SignOutAsync()
{
    等待 Context.SignOutAsync(IdentityConstants.ApplicationScheme);
    等待 Context.SignOutAsync(IdentityConstants.ExternalScheme);
    等待 Context.SignOutAsync( IdentityConstants.TwoFactorUserIdScheme );
}

(见源代码

通常,这些树身份验证方案通过以下方式自动注册AddIdentity<TUser, TRole>()

公共静态 IdentityBuilder AddIdentity<TUser, TRole>(
    这个IServiceCollection服务,
    操作 <IdentityOptions> setupAction)
{
    services.AddAuthentication(选项=>
    {
        options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
        options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
        options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
    })
    ...
    .AddCookie( IdentityConstants.TwoFactorUserIdScheme , o =>
    {
        o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
        o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
    });
    ... // 其他服务
}

(见源代码

但是,您添加了Identity服务,而AddIdentityCore<>()不是AddIdentity<>().

由于AddIdentityCore<>()不会自动注册TwoFactorUserIdScheme方案(请参阅源代码),因此没有关联的CookieAuthenticationHandlerfor TwoFactorUserIdScheme。结果,它抛出了。


怎么解决

为了使用SignInManager.SignOutAsync(),根据上述描述,我们需要确保<scheme>-<handler>已注册地图TwoFactorUserIdScheme

所以我将您的代码更改如下,现在它对我来说效果很好:

serviceCollection.AddAuthentication(IdentityConstants.ApplicationScheme)
    .AddCookie(IdentityConstants.ApplicationScheme, 选项 =>
    {
        选项.SlidingExpiration = true;
    })
    .AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>
    {
        o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
        o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
    })
    .AddGoogle(谷歌选项=>
    {
        this.Configuration.Bind("OAuth2:Providers:Google", googleOptions);
        googleOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
    })
    .AddExternalCookie();