在 ASP.NET 应用中共享身份验证 cookieShare authentication cookies among ASP.NET apps

本文内容

作者:Rick Anderson

网站通常由单独的 web 应用组成。若要提供单一登录(SSO)体验,站点内的 web 应用必须共享身份验证 cookie。若要支持这种情况下,数据保护堆栈允许在共享 Katana cookie 身份验证和 ASP.NET Core cookie 身份验证票证。

在下面的示例中:

  • 身份验证 cookie 名称设置为 .AspNet.SharedCookie的公共值。
  • AuthenticationType 设置为显式或默认情况下 Identity.Application
  • 常见的应用程序名称用于使数据保护系统共享数据保护密钥(SharedCookieApp)。
  • Identity.Application 用作身份验证方案。无论使用哪种方案,都必须在共享 cookie 应用内和中以一致的方式使用它,或者通过显式设置。加密和解密 cookie 时使用该方案,因此必须在应用间使用一致的方案。
  • 使用通用的数据保护密钥存储位置。
  • DataProtectionProvider 需要DataProtection NuGet 包:
  • SetApplicationName 设置通用应用名称。

与 ASP.NET Core 标识共享身份验证 cookieShare authentication cookies with ASP.NET Core Identity

当使用 ASP.NET Core标识:

Startup.ConfigureServices 中:

  1. services.AddDataProtection()
  2. .PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
  3. .SetApplicationName("SharedCookieApp");
  4. services.ConfigureApplicationCookie(options => {
  5. options.Cookie.Name = ".AspNet.SharedCookie";
  6. });

共享身份验证 cookie 但不 ASP.NET Core 标识Share authentication cookies without ASP.NET Core Identity

如果在不 ASP.NET Core 标识的情况下直接使用 cookie,请在 Startup.ConfigureServices中配置数据保护和身份验证。在下面的示例中,"身份验证类型" 设置为 Identity.Application

  1. services.AddDataProtection()
  2. .PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
  3. .SetApplicationName("SharedCookieApp");
  4. services.AddAuthentication("Identity.Application")
  5. .AddCookie("Identity.Application", options =>
  6. {
  7. options.Cookie.Name = ".AspNet.SharedCookie";
  8. });

跨不同的基路径共享 cookieShare cookies across different base paths

身份验证 cookie 使用HttpRequest. PathBase作为其默认的cookie。如果应用的 cookie 必须在不同的基本路径间共享,则必须重写 Path

  1. services.AddDataProtection()
  2. .PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
  3. .SetApplicationName("SharedCookieApp");
  4. services.ConfigureApplicationCookie(options => {
  5. options.Cookie.Name = ".AspNet.SharedCookie";
  6. options.Cookie.Path = "/";
  7. });

跨子域共享 cookieShare cookies across subdomains

承载跨子域共享 cookie 的应用时,请在 " Cookie " 属性中指定一个公共域。若要在 contoso.com上跨应用共享 cookie,如 first_subdomain.contoso.comsecond_subdomain.contoso.com,请将 Cookie.Domain 指定为 .contoso.com

  1. options.Cookie.Domain = ".contoso.com";

加密静态数据保护密钥Encrypt data protection keys at rest

对于生产部署,将 DataProtectionProvider 配置为使用 DPAPI 或 X509Certificate 加密静态密钥。有关详细信息,请参阅 在 ASP.NET Core 中存放的密钥加密在下面的示例中,提供了一个证书指纹来 ProtectKeysWithCertificate

  1. services.AddDataProtection()
  2. .ProtectKeysWithCertificate("{CERTIFICATE THUMBPRINT}");

在 ASP.NET 4.x 和 ASP.NET Core 应用之间共享身份验证 cookieShare authentication cookies between ASP.NET 4.x and ASP.NET Core apps

使用 Katana Cookie 身份验证中间件的 ASP.NET 4.x 应用程序可以配置为生成与 ASP.NET Core Cookie 身份验证中间件兼容的身份验证 cookie。这允许在多个步骤中升级大型站点的单个应用,同时跨站点提供平稳的 SSO 体验。

当应用使用 Katana Cookie 身份验证中间件时,它会调用项目的Startup.Auth.cs文件中的 UseCookieAuthentication使用 Visual Studio 2013 和更高版本创建的 ASP.NET 4.x web 应用项目默认使用 Katana Cookie 身份验证中间件。尽管 UseCookieAuthentication 已过时且不受 ASP.NET Core 应用的支持,但在使用 Katana Cookie 身份验证中间件的 ASP.NET 4.x 应用中调用 UseCookieAuthentication 是有效的。

ASP.NET 4.x 应用必须面向 .NET Framework 4.5.1 或更高版本。否则,无法安装所需的 NuGet 包。

若要在 ASP.NET 4.x 应用和 ASP.NET Core 应用之间共享身份验证 cookie,请按在ASP.NET Core 应用之间共享身份验证 cookie部分中所述配置 ASP.NET Core 应用,然后按如下所示配置 ASP.NET 4.x 应用。

确认应用的包已更新到最新版本。Owin包安装到每个 ASP.NET 1.x 应用程序中。

查找并修改对 UseCookieAuthentication的调用:

  • 更改 cookie 名称以匹配 ASP.NET Core Cookie 身份验证中间件使用的名称(示例中的.AspNet.SharedCookie)。
  • 在下面的示例中,"身份验证类型" 设置为 Identity.Application
  • 提供已初始化为通用数据保护密钥存储位置的 DataProtectionProvider 的实例。
  • 确认应用名称设置为共享身份验证 cookie 的所有应用使用的通用应用名称(在本示例中为SharedCookieApp)。

如果未设置 http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifierhttp://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider,请将 UniqueClaimTypeIdentifier 设置为区分唯一用户的声明。

App_Start/startup.auth.cs

  1. app.UseCookieAuthentication(new CookieAuthenticationOptions
  2. {
  3. AuthenticationType = "Identity.Application",
  4. CookieName = ".AspNet.SharedCookie",
  5. LoginPath = new PathString("/Account/Login"),
  6. Provider = new CookieAuthenticationProvider
  7. {
  8. OnValidateIdentity =
  9. SecurityStampValidator
  10. .OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
  11. validateInterval: TimeSpan.FromMinutes(30),
  12. regenerateIdentity: (manager, user) =>
  13. user.GenerateUserIdentityAsync(manager))
  14. },
  15. TicketDataFormat = new AspNetTicketDataFormat(
  16. new DataProtectorShim(
  17. DataProtectionProvider.Create("{PATH TO COMMON KEY RING FOLDER}",
  18. (builder) => { builder.SetApplicationName("SharedCookieApp"); })
  19. .CreateProtector(
  20. "Microsoft.AspNetCore.Authentication.Cookies." +
  21. "CookieAuthenticationMiddleware",
  22. "Identity.Application",
  23. "v2"))),
  24. CookieManager = new ChunkingCookieManager()
  25. });
  26. System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier =
  27. "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";

生成用户标识时,身份验证类型(Identity.Application)必须与App_Start/startup.auth.cs中的 UseCookieAuthentication AuthenticationType 集中定义的类型匹配。

模型/IdentityModels

  1. public class ApplicationUser : IdentityUser
  2. {
  3. public async Task<ClaimsIdentity> GenerateUserIdentityAsync(
  4. UserManager<ApplicationUser> manager)
  5. {
  6. // The authenticationType must match the one defined in
  7. // CookieAuthenticationOptions.AuthenticationType
  8. var userIdentity =
  9. await manager.CreateIdentityAsync(this, "Identity.Application");
  10. // Add custom user claims here
  11. return userIdentity;
  12. }
  13. }

使用公共用户数据库Use a common user database

如果应用使用相同的标识架构(同一版本标识),请确认每个应用的标识系统指向同一用户数据库。否则,当标识系统尝试将身份验证 cookie 中的信息与数据库中的信息进行匹配时,它将在运行时生成故障。

当标识架构在应用中不同时,通常是因为应用使用的是不同的标识版本,因此,在不重新映射和添加其他应用的标识架构中的列的情况下,不能使用最新版本的标识共享公共数据库。将其他应用程序升级到使用最新的标识版本通常更高效,以便应用可以共享公共数据库。

其他资源Additional resources