ASP.NET .Net 和 Core 上跨子域的身份 Cookie
ASP.NET Identity Cookie across subdomains on .Net and Core
我有很多应用程序托管在主域和子域上:
网站 A,ASP.NET (.Net Core 2.0) www.example.com
网站 B,ASP.NET MVC(4.7 .net Framework)位于 site.example.com
Website C, ASP.NET Identity (.Net Core 2.0) at account.example.com
网站 D,ASP.NET Webform (4.7 .net Framework) 在 file.example.com
我想在 account.example.com 上登录使用,验证后用户将被重定向到其他网站。他们将通过其他网站上的角色获得授权。
我正在尝试在这些网站之间共享 cookie,并且所有网站都托管在 Azure Web App。
我正在使用 ASP.NET Identity (.Net Core 2.0)。我正在使用内置的 cookie 身份验证。
如何在所有应用程序中使用数据保护并在它们之间共享 cookie。
对于数据保护,我的代码是:
services.AddDataProtection()
.SetApplicationName("example")
.PersistKeysToFileSystem(new DirectoryInfo(@"%HOME%\ASP.NET\DataProtection-Keys"))
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
对于 Cookie 身份验证,我的代码是:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
CookieDomain = ".example.com"
});
关于.Net Core,如果你想在多个站点之间共享你的cookie,你可以尝试以下方式来初始化它而不是UseCookieAuthentication:
services.AddAuthentication();
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax;
options.Cookie.Name = "CookieName";
//options.Cookie.Domain = ".localhost";
if (!CurrentEnvironment.IsDevelopment())
options.Cookie.Domain = CommonConfig.CookieDomain; // ".mydomain.com"
options.Cookie.HttpOnly = false;
options.Cookie.Expiration = TimeSpan.FromDays(5 * 30);
options.SlidingExpiration = true;
options.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.Always;
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logoff");
options.AccessDeniedPath = new PathString("/Account/Login");
var protectionProvider = DataProtectionProvider.Create(new DirectoryInfo(CommonConfig.PersistKeysStoreC));
options.DataProtectionProvider = protectionProvider;
// This adds claims data to the cookie...
options.Events.OnSignedIn = async (context) =>
{
System.Security.Claims.ClaimsIdentity identity = (System.Security.Claims.ClaimsIdentity)context.Principal.Identity;
UserManager<AppUser> userManager = context.HttpContext.RequestServices.GetService<UserManager<AppUser>>();
AppUser user = await userManager.GetUserAsync(context.Principal);
identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.NameIdentifier, user.Id.ToString()));
//identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Email, user.Email.ToString()));
//identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, user.LastName));
//identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.GivenName, user.FirstName));
};
});
当然,您需要为所有站点提供相同的 ProtectionProvider 路径。
我从这个 Microsoft 文档中得到了解决方案
Share cookies among apps with ASP.NET and ASP.NET Core
以及此 sub-domain 身份验证系统的示例代码
Cookie Sharing Sample App - GitHub
The sample illustrates cookie sharing across three apps that use cookie authentication:
- ASP.NET Core 2.0 Razor Pages 应用,不使用 ASP.NET Core Identity
- ASP.NET 具有 ASP.NET Core Identity
的 Core 2.0 MVC 应用程序
- ASP.NET Framework 4.6.1 MVC 应用 ASP.NET Identity
Put this code in your ConfigureServices method in Startup.cs
services.AddDataProtection()
.PersistKeysToFileSystem(GetKeyRingDirInfo())
.SetApplicationName("example");
services.ConfigureApplicationCookie(options =>
{
options.Cookie.Name = "example";
options.Cookie.Domain = ".example.com";
});
For KeyRing method
private DirectoryInfo GetKeyRingDirInfo()
{
var startupAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var applicationBasePath = System.AppContext.BaseDirectory;
var directoryInfo = new DirectoryInfo(applicationBasePath);
do
{
directoryInfo = directoryInfo.Parent;
var keyRingDirectoryInfo = new DirectoryInfo(Path.Combine(directoryInfo.FullName, "KeyRing"));
if (keyRingDirectoryInfo.Exists)
{
return keyRingDirectoryInfo;
}
}
while (directoryInfo.Parent != null);
throw new Exception($"KeyRing folder could not be located using the application root {applicationBasePath}.");
}
Note : You have to copy KeyRing file which is automatically generated on Identity application hosting server and manually paste to other sub-domain and main domain hosting server of other website to share cookie for authentication.
我有很多应用程序托管在主域和子域上:
网站 A,ASP.NET (.Net Core 2.0) www.example.com
网站 B,ASP.NET MVC(4.7 .net Framework)位于 site.example.com
Website C, ASP.NET Identity (.Net Core 2.0) at account.example.com
网站 D,ASP.NET Webform (4.7 .net Framework) 在 file.example.com
我想在 account.example.com 上登录使用,验证后用户将被重定向到其他网站。他们将通过其他网站上的角色获得授权。
我正在尝试在这些网站之间共享 cookie,并且所有网站都托管在 Azure Web App。
我正在使用 ASP.NET Identity (.Net Core 2.0)。我正在使用内置的 cookie 身份验证。
如何在所有应用程序中使用数据保护并在它们之间共享 cookie。
对于数据保护,我的代码是:
services.AddDataProtection()
.SetApplicationName("example")
.PersistKeysToFileSystem(new DirectoryInfo(@"%HOME%\ASP.NET\DataProtection-Keys"))
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
对于 Cookie 身份验证,我的代码是:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
CookieDomain = ".example.com"
});
关于.Net Core,如果你想在多个站点之间共享你的cookie,你可以尝试以下方式来初始化它而不是UseCookieAuthentication:
services.AddAuthentication();
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax;
options.Cookie.Name = "CookieName";
//options.Cookie.Domain = ".localhost";
if (!CurrentEnvironment.IsDevelopment())
options.Cookie.Domain = CommonConfig.CookieDomain; // ".mydomain.com"
options.Cookie.HttpOnly = false;
options.Cookie.Expiration = TimeSpan.FromDays(5 * 30);
options.SlidingExpiration = true;
options.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.Always;
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logoff");
options.AccessDeniedPath = new PathString("/Account/Login");
var protectionProvider = DataProtectionProvider.Create(new DirectoryInfo(CommonConfig.PersistKeysStoreC));
options.DataProtectionProvider = protectionProvider;
// This adds claims data to the cookie...
options.Events.OnSignedIn = async (context) =>
{
System.Security.Claims.ClaimsIdentity identity = (System.Security.Claims.ClaimsIdentity)context.Principal.Identity;
UserManager<AppUser> userManager = context.HttpContext.RequestServices.GetService<UserManager<AppUser>>();
AppUser user = await userManager.GetUserAsync(context.Principal);
identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.NameIdentifier, user.Id.ToString()));
//identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Email, user.Email.ToString()));
//identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, user.LastName));
//identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.GivenName, user.FirstName));
};
});
当然,您需要为所有站点提供相同的 ProtectionProvider 路径。
我从这个 Microsoft 文档中得到了解决方案
Share cookies among apps with ASP.NET and ASP.NET Core
以及此 sub-domain 身份验证系统的示例代码
Cookie Sharing Sample App - GitHub
The sample illustrates cookie sharing across three apps that use cookie authentication:
- ASP.NET Core 2.0 Razor Pages 应用,不使用 ASP.NET Core Identity
- ASP.NET 具有 ASP.NET Core Identity 的 Core 2.0 MVC 应用程序
- ASP.NET Framework 4.6.1 MVC 应用 ASP.NET Identity
Put this code in your ConfigureServices method in Startup.cs
services.AddDataProtection()
.PersistKeysToFileSystem(GetKeyRingDirInfo())
.SetApplicationName("example");
services.ConfigureApplicationCookie(options =>
{
options.Cookie.Name = "example";
options.Cookie.Domain = ".example.com";
});
For KeyRing method
private DirectoryInfo GetKeyRingDirInfo()
{
var startupAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var applicationBasePath = System.AppContext.BaseDirectory;
var directoryInfo = new DirectoryInfo(applicationBasePath);
do
{
directoryInfo = directoryInfo.Parent;
var keyRingDirectoryInfo = new DirectoryInfo(Path.Combine(directoryInfo.FullName, "KeyRing"));
if (keyRingDirectoryInfo.Exists)
{
return keyRingDirectoryInfo;
}
}
while (directoryInfo.Parent != null);
throw new Exception($"KeyRing folder could not be located using the application root {applicationBasePath}.");
}
Note : You have to copy KeyRing file which is automatically generated on Identity application hosting server and manually paste to other sub-domain and main domain hosting server of other website to share cookie for authentication.