如果你已经有一个基于 ASP.NET 或 ASP.NET Core 的登录系统,并且你希望使用这个系统登录 Limyee CMS,那么你应该使用 Forms 认证。
启用 Forms SSO 后,会发生以下情况:
Forms SSO 通过 HTTP Cookie 将有关登录用户的安全消息从您的外部系统传递到 Limyee CMS。此消息是使用 ASP.NET 或 ASP.NET Core 提供的用户登录方式生成的。Limyee CMS 会自动验证消息并生成上下文用户。
当用户登录到您的主单点登录系统时,它将使用 ASP.NET 或 ASP.NET Core 的登录方式,并创建一个 Cookie,其中包含有关用户会话的数据。 当用户访问您的 Limyee CMS 时,Limyee CMS 将读取此 Cookie 会话数据。 如果存在给定用户名的用户,则登录该用户。 如果该用户不存在,则使用指定的会话数据创建一个新用户,然后登录该用户。
要使 Forms SSO 正常工作,Cookie 需要在外部身份验证系统和平台之间共享。 由于浏览器允许共享 cookie 的方式,这意味着您的平台和登录页面必须使用相同的域名。 例如,login.example.com 和 mobile.example.com 使用相同的域:.example.com,因此可以与Forms SSO一起使用。请转到“系统管理>身份验证>域名”进行设置。
要使不同的系统能交互登录信息,必须使用相同的密钥保护数据,并将密钥设置相同的应用名。还应使用相同的授权方案类型,设置相同的 cookie 名称。
ASP.NET
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
// Settings to configure shared cookie with ASP.NET Core app
CookieName = ".Limyee",
CookieDomain = ".example.com",
CookieHttpOnly = true,
AuthenticationType = "Authentication",
TicketDataFormat = new AspNetTicketDataFormat(
new DataProtectorShim(
DataProtectionProvider.Create(new DirectoryInfo("PATH TO COMMON KEY RING FOLDER"),
// Application name must be corresponding with Limyee CMS
builder => builder.SetApplicationName("LimyeeApp"))
.CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware",
// Must match the Scheme name used in the ASP.NET Core app, i.e. IdentityConstants.ApplicationScheme
"Authentication",
"v2"))),
CookieManager = new ChunkingCookieManager()
});
ASP.NET Core
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo("PATH TO COMMON KEY RING FOLDER"))
// Application name must be corresponding with Limyee CMS
.SetApplicationName("LimyeeApp");
//set default authentication schemes
var authenticationBuilder = services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = "Authentication";
options.DefaultScheme = "Authentication";
options.DefaultSignInScheme = "Authentication";
});
//add main cookie authentication
authenticationBuilder.AddCookie("Authentication", options =>
{
options.Cookie.Name = ".Limyee";
options.Cookie.HttpOnly = true;
options.Cookie.Domain = ".example.com";
});
|
名称 |
值 |
类型 |
描述 |
必填 |
|
电子邮件 |
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress |
|
用于获取用户的电子邮件地址的类型。用户的电子邮件地址必须是唯一的。 |
否 |
|
个人资料 |
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/profile |
string |
用于获取用户的个人资料类型,并更新用户的个人资料。 |
否 |
|
角色 |
http://schemas.microsoft.com/ws/2008/06/identity/claims/role |
string |
用于获取用户的角色类型,用于更新用户的角色。 |
否 |
序列化为多值的类型
CommonName=EXAMPL&Timezone=China+Standard+Time%3b480%3b(UTC%2b08%3a00)+Beijing%2c+Chongqing%2c+Hong+Kong%2c+Urumqi%3bChina+Standard+Time%3bChina+Daylight+Time%3b%3b
包含用户的昵称:CommonName 和用户资料包括但不全包括以下:
以英文逗号(,)相隔的 CSV 格式列表,用户将自动添加到 Everyone 和 Registered Users 角色中,而无需任何指派。
roles=Administrators,Moderators
登录系统需要登入用户时,创建声明数据,以便 Limyee CMS 读取。声明的颁发者(Issuer)参数为 Limyee CMS 的 tenant ID。如果你 Limyee CMS 未开启租赁模式,则 tenant ID 为空的 GUID。
ASP.NET
通常在文件 Models/IdentityModels.cs
public class ApplicationUser : IdentityUser
{
public ClaimsIdentity GenerateUserIdentity(ApplicationUserManager manager)
{
// Note the authenticationType must match the one defined in UseCookieAuthentication
var userIdentity = manager.CreateIdentity(this, "Authentication");
// Add custom user claims here
var claimsIssuer = Guid.Empty.ToString();
userIdentity.AddClaim(new Claim(ClaimTypes.Name, "example", ClaimValueTypes.String, claimsIssuer));
userIdentity.AddClaim(new Claim(ClaimTypes.Email, "example@example.com", ClaimValueTypes.Email, claimsIssuer));
userIdentity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/profile", "CommonName=EXAMPL&Timezone=China+Standard+Time%3b480%3b(UTC%2b08%3a00)+Beijing%2c+Chongqing%2c+Hong+Kong%2c+Urumqi%3bChina+Standard+Time%3bChina+Daylight+Time%3b%3b", ClaimValueTypes.String, claimsIssuer));
userIdentity.AddClaim(new Claim(ClaimTypes.Role, "roles=Administrators", ClaimValueTypes.String, claimsIssuer));
return userIdentity;
}
public Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
{
return Task.FromResult(GenerateUserIdentity(manager));
}
}
ASP.NET Core
public async Task UserSignInAsync(HttpContext context)
{
var claimsIssuer = Guid.Empty.ToString();
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, "example", ClaimValueTypes.String, claimsIssuer),
new Claim(ClaimTypes.Email, "example@example.com", ClaimValueTypes.Email, claimsIssuer),
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/profile", "CommonName=EXAMPL&Timezone=China+Standard+Time%3b480%3b(UTC%2b08%3a00)+Beijing%2c+Chongqing%2c+Hong+Kong%2c+Urumqi%3bChina+Standard+Time%3bChina+Daylight+Time%3b%3b", ClaimValueTypes.String, claimsIssuer),
new Claim(ClaimTypes.Role, "roles=Administrators", ClaimValueTypes.String, claimsIssuer)
};
//create principal for the current authentication scheme
var userIdentity = new ClaimsIdentity(claims, AuthenticationDefaults.AuthenticationScheme);
var userPrincipal = new ClaimsPrincipal(userIdentity);
//set value indicating whether session is persisted and the time at which the authentication was issued
var authenticationProperties = new AuthenticationProperties
{
IsPersistent = true,
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddDays(7)
};
//sign in
await context.SignInAsync(AuthenticationDefaults.AuthenticationScheme, userPrincipal, authenticationProperties);
}
Limyee CMS 是使用基于 ASP.NET 或 ASP.NET Core 的 HttpContext 进行登录,如果 Limyee CMS 无法处理 SSO cookie,HttpContext 的 User 将设置为未认证,用户无法登录到系统,此过程不会抛出错误。你需查看子域名、密钥、授权方案类型和声明等的设置是否一致。
如果您无法访问控制面板(例如,由于 Forms SSO 配置问题而无法再登录),则可以使用紧急访问页面返回您的平台。您必须在服务器上访问此页面。页面地址: {{Limyee Site Url}}/localaccess,它将允许您在启用 Forms SSO 插件之前使用凭据登录。
您不应使用电子邮件地址作为用户名。用户名用作平台中用户的可见唯一标识符,因此,如果使用电子邮件地址代替用户名将导致用户的电子邮件地址公开。如果您的现有系统使用电子邮件地址作为用户名,那么您应该考虑使用其他内容作为用户名,例如整数,UUID标识符,或者让用户在首次登录平台时创建其用户名。
参考:Share authentication cookies among ASP.NET apps | Microsoft Learn