Identity API によって生成された Cookie 内にユーザーからのカスタム データを保存する方法はありますか?
マルチテナント アプリケーションを構築しているため、複数の企業がアプリケーションの同じインスタンスにアクセスできます。そのため、特定のユーザーについては、ユーザーの会社コードを ID Cookie に保存して、ブラウザーを閉じた後に Web アプリケーションに戻ったときにユーザーからデータを取得する必要があります。
Identity API によって生成された Cookie 内にユーザーからのカスタム データを保存する方法はありますか?
マルチテナント アプリケーションを構築しているため、複数の企業がアプリケーションの同じインスタンスにアクセスできます。そのため、特定のユーザーについては、ユーザーの会社コードを ID Cookie に保存して、ブラウザーを閉じた後に Web アプリケーションに戻ったときにユーザーからデータを取得する必要があります。
カスタム UserClaimsPrincipalFactory を実装し、店舗番号のカスタム クレームを追加することでそれを実現できます。その後、他のクレームと共に Cookie に格納されます。
以下は、シナリオもマルチテナントであるため、SiteGuid を含むいくつかのカスタム クレームを追加している私のプロジェクトのサンプル コードです。
using cloudscribe.Core.Models;
using Microsoft.AspNet.Identity;
using Microsoft.Extensions.OptionsModel;
using System;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
namespace cloudscribe.Core.Identity
{
public class SiteUserClaimsPrincipalFactory<TUser, TRole> : UserClaimsPrincipalFactory<TUser, TRole>
where TUser : SiteUser
where TRole : SiteRole
{
public SiteUserClaimsPrincipalFactory(
ISiteRepository siteRepository,
SiteUserManager<TUser> userManager,
SiteRoleManager<TRole> roleManager,
IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor)
{
if (siteRepository == null) { throw new ArgumentNullException(nameof(siteRepository)); }
siteRepo = siteRepository;
options = optionsAccessor.Value;
}
private ISiteRepository siteRepo;
private IdentityOptions options;
public override async Task<ClaimsPrincipal> CreateAsync(TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
var userId = await UserManager.GetUserIdAsync(user);
var userName = await UserManager.GetUserNameAsync(user);
var id = new ClaimsIdentity(
options.Cookies.ApplicationCookie.AuthenticationScheme,
Options.ClaimsIdentity.UserNameClaimType,
Options.ClaimsIdentity.RoleClaimType
);
id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId));
id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName));
if (UserManager.SupportsUserSecurityStamp)
{
id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType,
await UserManager.GetSecurityStampAsync(user)));
}
if (UserManager.SupportsUserRole)
{
var roles = await UserManager.GetRolesAsync(user);
foreach (var roleName in roles)
{
id.AddClaim(new Claim(Options.ClaimsIdentity.RoleClaimType, roleName));
if (RoleManager.SupportsRoleClaims)
{
var role = await RoleManager.FindByNameAsync(roleName);
if (role != null)
{
id.AddClaims(await RoleManager.GetClaimsAsync(role));
}
}
}
}
if (UserManager.SupportsUserClaim)
{
id.AddClaims(await UserManager.GetClaimsAsync(user));
}
ClaimsPrincipal principal = new ClaimsPrincipal(id);
if (principal.Identity is ClaimsIdentity)
{
ClaimsIdentity identity = (ClaimsIdentity)principal.Identity;
Claim displayNameClaim = new Claim("DisplayName", user.DisplayName);
if (!identity.HasClaim(displayNameClaim.Type, displayNameClaim.Value))
{
identity.AddClaim(displayNameClaim);
}
Claim emailClaim = new Claim(ClaimTypes.Email, user.Email);
if (!identity.HasClaim(emailClaim.Type, emailClaim.Value))
{
identity.AddClaim(emailClaim);
}
ISiteSettings site = await siteRepo.Fetch(user.SiteId, CancellationToken.None);
if (site != null)
{
Claim siteGuidClaim = new Claim("SiteGuid", site.SiteGuid.ToString());
if (!identity.HasClaim(siteGuidClaim.Type, siteGuidClaim.Value))
{
identity.AddClaim(siteGuidClaim);
}
}
}
return principal;
}
}
}
次に、スタートアップで、カスタム ファクトリを登録して、デフォルトのファクトリの代わりに注入して使用する必要があります。
services.AddScoped<IUserClaimsPrincipalFactory<SiteUser>, SiteUserClaimsPrincipalFactory<SiteUser, SiteRole>>();
もう 1 つのアプローチはクレーム変換を使用することですが、このアプローチは余分なクレームを Cookie に保存せず、代わりに要求ごとにクレームを更新します。 Cookie のクレームを変更しないでください。
public class ClaimsTransformer : IClaimsTransformer
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
((ClaimsIdentity)principal.Identity).AddClaim(new Claim("ProjectReader", "true"));
return Task.FromResult(principal);
}
}
次に、startup.cs で:
app.UseClaimsTransformation(new ClaimsTransformationOptions
{
Transformer = new ClaimsTransformer()
});