ASP.Net Core 2.2 SignInManager'没有为方案'Identity.Application'注册任何登录身份验证处理程序

时间:2019-06-10 05:53:11

标签: authentication asp.net-core cookies asp.net-core-identity

我在Startup.cs中具有以下配置:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    //options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o => {
    o.LoginPath = Routes.Urls.AdminAccountLogin;
    o.AccessDeniedPath = Routes.Urls.AdminAccountAccessdenied;
}).AddJwtBearer(configureOptions => {});

当控制器“登录”操作调用SignInManger.PasswordSignInAsync时,应用程序将引发以下异常:

  

发生异常:CLR / System.InvalidOperationException
  引发的异常:System.Private.CoreLib.dll中的'System.InvalidOperationException':'未为方案'Identity.Application'注册任何登录身份验证处理程序。注册的登录方案为:Cookies。您是否忘记了调用AddAuthentication()。AddCookies(“ Identity.Application”,...)?'

Identity.Application来自哪里?

1 个答案:

答案 0 :(得分:0)

简短(不那么有用)答案:

具体来说,它来自microsoft.aspnetcore.identity类中的Microsoft.AspNetCore.Identity.IdentityConstants.ApplicationScheme

长答案,以及整个细分:

您需要添加身份-该方案已建立,并已通过AddIdentity扩展方法连接到身份验证

扩展方法在Microsoft.Extensions.DependencyInjection.IdentityServiceCollectionExtensions

public static IdentityBuilder AddIdentity<TUser, TRole>(this IServiceCollection services, Action<IdentityOptions> setupAction) where TUser: class where TRole: class
        {
            services.AddAuthentication(delegate (AuthenticationOptions options) {
                options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
                options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
                options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
            }).AddCookie(IdentityConstants.ApplicationScheme, delegate (CookieAuthenticationOptions o) {
                o.LoginPath = new PathString("/Account/Login");
                CookieAuthenticationEvents events1 = new CookieAuthenticationEvents();
                events1.OnValidatePrincipal = new Func<CookieValidatePrincipalContext, Task>(SecurityStampValidator.ValidatePrincipalAsync);
                o.Events = events1;
            }).AddCookie(IdentityConstants.ExternalScheme, delegate (CookieAuthenticationOptions o) {
                o.Cookie.Name = IdentityConstants.ExternalScheme;
                o.ExpireTimeSpan = TimeSpan.FromMinutes((double) 5.0);
            }).AddCookie(IdentityConstants.TwoFactorRememberMeScheme, delegate (CookieAuthenticationOptions o) {
                o.Cookie.Name = IdentityConstants.TwoFactorRememberMeScheme;
                CookieAuthenticationEvents events1 = new CookieAuthenticationEvents();
                events1.OnValidatePrincipal = new Func<CookieValidatePrincipalContext, Task>(SecurityStampValidator.ValidateAsync<ITwoFactorSecurityStampValidator>);
                o.Events = events1;
            }).AddCookie(IdentityConstants.TwoFactorUserIdScheme, delegate (CookieAuthenticationOptions o) {
                o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
                o.ExpireTimeSpan = TimeSpan.FromMinutes((double) 5.0);
            });
            services.AddHttpContextAccessor();
            services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
            services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
            services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
            services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
            services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();
            services.TryAddScoped<IdentityErrorDescriber>();
            services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
            services.TryAddScoped<ITwoFactorSecurityStampValidator, TwoFactorSecurityStampValidator<TUser>>();
            services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
            services.TryAddScoped<UserManager<TUser>>();
            services.TryAddScoped<SignInManager<TUser>>();
            services.TryAddScoped<RoleManager<TRole>>();
            if (setupAction != null)
            {
                services.Configure<IdentityOptions>(setupAction);
            }
            return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
        }

如果您遵循此AddCookie通话

.AddCookie(IdentityConstants.ApplicationScheme, delegate (CookieAuthenticationOptions o) {
                o.LoginPath = new PathString("/Account/Login");
                CookieAuthenticationEvents events1 = new CookieAuthenticationEvents();
                events1.OnValidatePrincipal = new Func<CookieValidatePrincipalContext, Task>(SecurityStampValidator.ValidatePrincipalAsync);
                o.Events = events1;

它最终使用“ Identity.Application”方案和AuthenticationOptions

配置CookieAuthenticationHandler

致电SignInManager.PasswordSignInAsync时:

  • SignInManager检查数据库中的用户名/密码(如果启用,则进行两个因素的处理),然后检查是否有效
  • 使用身份应用方案创建ClaimsPrincipal并将其发送到HttpContext.SignInAsync(扩展方法),请参见here
  • 哪个获取了IAuthenticationService(由AddAuthentication添加到DI),请参见here
  • AuthenticationService中,它使用了一系列对象
    • IAuthenticationHandlerProvider => IAuthenticationSchemeProvider =>先前配置的AuthenticationOptions构成AuthenticationScheme,在此情况下IAuthenticationHandlerCookieAuthenticationHandler提供服务。参见hereherehere
    • CookieAuthenticationHandler.HandleSignInAsync创建,加密和添加cookie。

现在cookie在那里,因此调用AuthenticationMiddleware中的下一个请求(通常是登录后的重定向),即HttpContext.AuthenticateAsync方法,其流程类似于

  • CookieAuthenticationHandler.HandleAuthenticateAsync,它将读取Cookie并传回ClaimsPrincipal
  • 此对象已分配给HttpContext.User,使其可以访问请求管道的所有其他区域,例如授权,请参见here