CookieAuthenticationOptions.AuthenticationType有什么用?

What is CookieAuthenticationOptions.AuthenticationType used for?

在我的应用程序的 Asp.Net Identity Auth 中间件设置中,我有

app.UseCookieAuthentication(new CookieAuthenticationOptions {
    LoginPath = new PathString("/Login/"),
    //AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    Provider = new CookieAuthenticationProvider {
    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<MyUserManager, MyUser>(
                        TimeSpan.FromMinutes(30),
                        (manager, user) => manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)
                    ),
    },
});

我从另一个应用程序复制了这个,我只是注意到如果我取消注释 AuthenticationType 行,登录成功(我在我的记录器中收到一条从我的控制器写入的成功消息)但总是重定向回登录屏幕。

documentation for CookieAuthenticationOptions 它说

The AuthenticationType in the options corresponds to the IIdentity AuthenticationType property. A different value may be assigned in order to use the same authentication middleware type more than once in a pipeline.(Inherited from AuthenticationOptions.)

我真的不明白这是什么意思,为什么这会导致我的登录请求被重定向(在成功登录之后),也不明白这个选项 是什么有用。

我不知道完整的答案,但我有一个例子可以说明 的用途。

我有一个多租户网站:该网站作为单个实例运行,多个域链接到它。每个域都是一个单独的租户(具有一组单独的用户)。要为每个租户实现 Facebook 登录,我需要为每个租户开发一个 Facebook 应用程序。要配置它,我必须为每个租户设置一个唯一的 CallbackPath 一个唯一的 AuthenticationType:

var facebookOptions = new FacebookAuthenticationOptions
{
    AuthenticationType = "Facebook-{tenantID}", 
    CallbackPath = new PathString($"/signin-facebook-{tenantID}")
}

我认为它也被用作 cookie 名称,但对于像 FacebookAuthentication 这样的外部登录,情况并非如此。我注意到的是,请求时弹出了 AuthenticationType 的这个值:

  1. IdentityUserLogin.LoginProvider 通过 authenticationManager.GetExternalLoginInfoAsync()
  2. AuthenticationDescription.AuthenticationType 通过 authenticationManager.GetExternalAuthenticationTypes()(似乎合乎逻辑 ;-))
  3. 每个user.Logins的IdentityUserLogin.LoginProvider(类似于1)

最后但同样重要的是:AuthenticationType 的值存储在数据库列 AspNetUserLogins.LoginProvider。

这是一个字符串,可以是任何东西。但这是身份验证类型的标识符。您可以有多种身份验证类型:您的数据库与用户、Google、Facebook 等。据我所知,这是作为声明添加到登录时生成的 cookie 中的。

注销用户时,您需要知道身份验证提供程序。如果你的认证中间件是这样定义的:

    app.UseCookieAuthentication(new CookieAuthenticationOptions {
        LoginPath = new PathString("/Login/"),
        AuthenticationType = "My-Magical-Authentication",
        // etc...
        },
    });

然后要注销用户,您需要相同的魔术字符串:AuthenticationManager.SignOut("My-Magical-Authentication")

创建主体时,此字符串也会传递到 ClaimsIdentity。并且没有 AuthenticationType 主体无法进行身份验证 because:

/// <summary>
/// Gets a value that indicates whether the identity has been authenticated.
/// </summary>
/// 
/// <returns>
/// true if the identity has been authenticated; otherwise, false.
/// </returns>
public virtual bool IsAuthenticated
{
  get
  {
    return !string.IsNullOrEmpty(this.m_authenticationType);
  }
}

此方法 IsAuthenticated 在整个 MVC 代码库中使用,所有身份验证机制都依赖于此。

此外,理论上您可以通过多个提供者登录,一次只注销其中一个,而其余提供者仍然经过身份验证。虽然我从来没有尝试过这个。

我刚刚发现的另一种用法 - 如果您不在中间件配置中提供 CookieName,则 Options.CookieName = CookieAuthenticationDefaults.CookiePrefix + Options.AuthenticationType; (see second if statement in constructor).

我敢肯定还有更多地方使用它。但最重要的是提供它并与名称保持一致,否则您将在身份验证系统中遇到细微的错误。

如果您设置全新的 asp.net 解决方案,Startup.Auth 中的标准设置代码(与您从其他应用复制的代码相对)包括AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,

这会创建一个 cookie(默认名称为 .AspNet.ApplicationCookie),您可以在浏览器的活动 cookie 列表中看到它,用于(除其他外)检查是否用户对每个请求都进行了身份验证。如果 cookie 不存在(或者用户在某种程度上未通过身份验证),中间件将重定向到您在 LoginPath = new PathString("/Login/"),

行中指定的路由

这一行在您的代码中被注释掉并且您的应用程序正常运行这一事实表明您的代码中存在一些其他非标准配置来对用户进行身份验证。如果您取消注释此行并且登录成功但重定向回登录,这表明非标准代码与中间件之间存在一些冲突,导致中间件确定用户未通过身份验证,并被重定向回 LoginPath .

我会找出你的应用程序中是否存在非标准的身份验证代码,并确定它具体做了什么,冲突的答案应该会出现。一般建议是不要更改标准身份验证代码,除非您确切知道这样做的含义(并且它可能会变得复杂,粗心的人会遇到很多陷阱)。

具体针对您的问题,此选项不仅有用,而且是身份中间件标准操作的基础。您的应用程序中似乎包含非标准代码。如果是这样,您应该完全确定它在登录安全方面的作用(及其影响),或者如果可以的话恢复为标准身份代码。