ASP.NET Core Identity userManager.AddToRoleAsync() - 按 id 添加
ASP.NET Core Identity userManager.AddToRoleAsync() - add by id
我有一个自定义用户角色 class,其中 CompanyId
作为外键。所以我可以创建与公司相关的用户角色。这意味着管理员角色或任何其他角色本身可以在多个公司中。我不能与 Company 和 Role 建立多对多关系,因为 Administrator 对一家公司的要求可能因另一家公司而异。所以我在用户角色实体中添加了公司ID。
我的问题是,用户管理器在 AddToRoleAsync()
中将角色名称作为参数,我不能使用它,因为角色名称可能是多余的。如果我能够通过 Id 添加用户角色,那就太好了。有解决办法吗?
我目前的解决方法是将公司名称添加为角色名称的前缀。喜欢:ABC - 管理员; XYZ - 管理员。我不太喜欢这个,用户也不会。
如果我可以为 AddToRoleAsync()
和 IsInRoleAync()
创建一个重载方法来通过 ID 而不是名称来查找角色,那就太好了。
您可以扩展 UserManager
class 并添加另一种方法来通过 RoleId
添加角色
public class ApplicationUserManager : UserManager<IdentityUser>
{
private readonly UserStore<IdentityUser, IdentityRole, ApplicationDbContext, string, IdentityUserClaim<string>,
IdentityUserRole<string>, IdentityUserLogin<string>, IdentityUserToken<string>, IdentityRoleClaim<string>> _store;
public ApplicationUserManager(
IUserStore<IdentityUser> store,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<IdentityUser> passwordHasher,
IEnumerable<IUserValidator<IdentityUser>> userValidators,
IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<UserManager<IdentityUser>> logger)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
_store = (UserStore<IdentityUser, IdentityRole, ApplicationDbContext, string, IdentityUserClaim<string>,
IdentityUserRole<string>, IdentityUserLogin<string>, IdentityUserToken<string>, IdentityRoleClaim<string>>)store;
}
public virtual async Task<IdentityResult> AddToRoleByRoleIdAsync(IdentityUser user, string roleId)
{
ThrowIfDisposed();
if (user == null)
throw new ArgumentNullException(nameof(user));
if (string.IsNullOrWhiteSpace(roleId))
throw new ArgumentNullException(nameof(roleId));
if (await IsInRoleByRoleIdAsync(user, roleId, CancellationToken))
return IdentityResult.Failed(ErrorDescriber.UserAlreadyInRole(roleId));
_store.Context.Set<IdentityUserRole<string>>().Add(new IdentityUserRole<string> { RoleId = roleId, UserId = user.Id });
return await UpdateUserAsync(user);
}
public async Task<bool> IsInRoleByRoleIdAsync(IdentityUser user, string roleId, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
throw new ArgumentNullException(nameof(user));
if (string.IsNullOrWhiteSpace(roleId))
throw new ArgumentNullException(nameof(roleId));
var role = await _store.Context.Set<IdentityRole>().FindAsync(roleId);
if (role == null)
return false;
var userRole = await _store.Context.Set<IdentityUserRole<string>>().FindAsync(new object[] { user.Id, roleId }, cancellationToken);
return userRole != null;
}
}
然后注册你自己的 UserManager
:
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserManager<ApplicationUserManager>() // Add ApplicationUserManager
.AddDefaultTokenProviders()
.AddDefaultUI();
最后:
await _userManager.AddToRoleByRoleIdAsync(user, role.Id);
我有一个自定义用户角色 class,其中 CompanyId
作为外键。所以我可以创建与公司相关的用户角色。这意味着管理员角色或任何其他角色本身可以在多个公司中。我不能与 Company 和 Role 建立多对多关系,因为 Administrator 对一家公司的要求可能因另一家公司而异。所以我在用户角色实体中添加了公司ID。
我的问题是,用户管理器在 AddToRoleAsync()
中将角色名称作为参数,我不能使用它,因为角色名称可能是多余的。如果我能够通过 Id 添加用户角色,那就太好了。有解决办法吗?
我目前的解决方法是将公司名称添加为角色名称的前缀。喜欢:ABC - 管理员; XYZ - 管理员。我不太喜欢这个,用户也不会。
如果我可以为 AddToRoleAsync()
和 IsInRoleAync()
创建一个重载方法来通过 ID 而不是名称来查找角色,那就太好了。
您可以扩展 UserManager
class 并添加另一种方法来通过 RoleId
public class ApplicationUserManager : UserManager<IdentityUser>
{
private readonly UserStore<IdentityUser, IdentityRole, ApplicationDbContext, string, IdentityUserClaim<string>,
IdentityUserRole<string>, IdentityUserLogin<string>, IdentityUserToken<string>, IdentityRoleClaim<string>> _store;
public ApplicationUserManager(
IUserStore<IdentityUser> store,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<IdentityUser> passwordHasher,
IEnumerable<IUserValidator<IdentityUser>> userValidators,
IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<UserManager<IdentityUser>> logger)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
_store = (UserStore<IdentityUser, IdentityRole, ApplicationDbContext, string, IdentityUserClaim<string>,
IdentityUserRole<string>, IdentityUserLogin<string>, IdentityUserToken<string>, IdentityRoleClaim<string>>)store;
}
public virtual async Task<IdentityResult> AddToRoleByRoleIdAsync(IdentityUser user, string roleId)
{
ThrowIfDisposed();
if (user == null)
throw new ArgumentNullException(nameof(user));
if (string.IsNullOrWhiteSpace(roleId))
throw new ArgumentNullException(nameof(roleId));
if (await IsInRoleByRoleIdAsync(user, roleId, CancellationToken))
return IdentityResult.Failed(ErrorDescriber.UserAlreadyInRole(roleId));
_store.Context.Set<IdentityUserRole<string>>().Add(new IdentityUserRole<string> { RoleId = roleId, UserId = user.Id });
return await UpdateUserAsync(user);
}
public async Task<bool> IsInRoleByRoleIdAsync(IdentityUser user, string roleId, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
throw new ArgumentNullException(nameof(user));
if (string.IsNullOrWhiteSpace(roleId))
throw new ArgumentNullException(nameof(roleId));
var role = await _store.Context.Set<IdentityRole>().FindAsync(roleId);
if (role == null)
return false;
var userRole = await _store.Context.Set<IdentityUserRole<string>>().FindAsync(new object[] { user.Id, roleId }, cancellationToken);
return userRole != null;
}
}
然后注册你自己的 UserManager
:
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserManager<ApplicationUserManager>() // Add ApplicationUserManager
.AddDefaultTokenProviders()
.AddDefaultUI();
最后:
await _userManager.AddToRoleByRoleIdAsync(user, role.Id);