我正在尝试使用Identity w / o EntityFramework创建一个.net Core解决方案,但使用整数ID(UserId和RoleId)。我已经按照这个基本设置来创建解决方案并删除EF(https://taherchhabra.github.io/jekyll/update/2016/09/22/aspnet-core-identity-without-entityframework.html),但这仍然有用户的愚蠢的Guid id列。当我尝试更改它时,我在创建UserStore
时遇到了一个问题,因为它继承自IUserStore<User>
,这需要我实现
Task<User> FindByIdAsync(string userId, CancellationToken cancellationToken)
其中或者当然意味着Id值是字符串而不是int。
我已经阅读了几个关于如何更改基于EF的解决方案以使用整数的内容,我挖掘了EF如何做到这一点,但它都基于使用TKey
的EF类。
我尝试创建自己的IUserStore来将字符串更改为整数但是项目甚至不会旋转(它会编译正常但是当我尝试在本地运行它时会在完成旋转之前退出)。
有谁知道如何做到这一点?我搜索了很多,找不到任何东西。
修改 到目前为止我所做的是创建我自己的UserStore和RollStore(它们基本上只是我工作时会调整的原件的副本)。在我的HomeController中,我添加了以下内容:
public class HomeController : Controller
{
private readonly UserManager<models.User> _userManager;
public HomeController(UserManager<models.User> userManager)
{
_userManager = userManager;
}
public async Task<IActionResult> Index()
{
var user = new models.User();
if(User.Identity.IsAuthenticated)
user = await _userManager.FindByNameAsync(User.Identity.Name);
return View();
}
}
这基本上是“插入的”测试,我可以在调试器中单步执行。
在我的Startup.cs
:
services.AddSingleton<IUserStore<User>, UserStore>();
services.AddSingleton<IRoleStore<Role>, RoleStore>();
services.AddIdentity<User, Role>()
.AddDefaultTokenProviders();
这实际上会起作用(通过我的端点进行调试,正确填充user
)。但是,如果我仔细观察,我会发现IUserStore
和IRoleStore
是Microsoft.AspNetCore.Identity
版本,这意味着我仍然依赖于这些合同,并且我需要使用Guid作为ID。
如果我强制解决问题,请使用
services.AddSingleton<SandboxCoreDapper.Identity.Interfaces.IUserStore<User>, UserStore>();
services.AddSingleton<SandboxCoreDapper.Identity.Interfaces.IRoleStore<Role>, RoleStore>();
然后当我尝试点击我的端点时,UserManager将无法解析:
“无法解析类型'Microsoft.AspNetCore.Identity.IUserStore 1[SandboxCoreDapper.Models.User]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager
1 [SandboxCoreDapper.Models.User]'的服务。”
编辑2 我发现了这个有趣的讨论:https://github.com/aspnet/Identity/issues/493
基于此我已经开始创建我自己的RoleManager
和UserManager
,这基本上只是扩展了身份版本:
namespace SandboxCoreDapper.Identity.Services
{
public class UserManager<TUser> : Microsoft.AspNetCore.Identity.UserManager<TUser> where TUser : class
{
public UserManager(
sandyId.IUserStore<TUser> store, // my version of IUserStore
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<TUser> passwordHasher,
IEnumerable<IUserValidator<TUser>> userValidators,
IEnumerable<IPasswordValidator<TUser>> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<UserManager<TUser>> logger)
:base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
}
}
}
同样适用于RoleManager
。
然后我添加到Startup.cs
services.AddIdentity<User, Role>()
.AddDefaultTokenProviders()
.AddUserManager<SandboxCoreDapper.Identity.Services.UserManager<User>>()
.AddRoleManager<SandboxCoreDapper.Identity.Services.RoleManager<Role>>()
;
到目前为止一直很好......
答案 0 :(得分:1)
这是对我的评论以及您的问题/评论的回应:
只需声明自己的UserStore,然后在Startup.cs中注册它。
以下是我对UserStore的实现以适应这种情况:
public class UserStore : IUserPasswordStore<Login>, IUserEmailStore<Login>, IUserPhoneNumberStore<Login>
{
private readonly IAccountRepo _accountRepo;
public UserStore(IAccountRepo accountRepo)
{
_accountRepo = accountRepo;
}
public void Dispose()
{
}
public async Task<string> GetUserIdAsync(Login user, CancellationToken cancellationToken)
{
return await Task.FromResult(user.Username);
}
public async Task<string> GetUserNameAsync(Login user, CancellationToken cancellationToken)
{
return await Task.FromResult(user.Username);
}
public Task SetUserNameAsync(Login user, string userName, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetNormalizedUserNameAsync(Login user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public async Task SetNormalizedUserNameAsync(Login user, string normalizedName, CancellationToken cancellationToken)
{
await Task.FromResult(user.Username = normalizedName.ToLower());
}
public async Task<IdentityResult> CreateAsync(Login user, CancellationToken cancellationToken)
{
await _accountRepo.CreateLogin(user);
return IdentityResult.Success;
}
public async Task<IdentityResult> UpdateAsync(Login user, CancellationToken cancellationToken)
{
await _accountRepo.UpdateLogin(user.LoginId, user.Email, true);
return IdentityResult.Success;
}
public Task<IdentityResult> DeleteAsync(Login user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public async Task<Login> FindByIdAsync(string userId, CancellationToken cancellationToken)
{
return await _accountRepo.GetUser(userId);
}
public async Task<Login> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
return await _accountRepo.GetUser(normalizedUserName);
}
public async Task SetPasswordHashAsync(Login user, string passwordHash, CancellationToken cancellationToken)
{
if (user.LoginId != 0)
{
await _accountRepo.ChangePassword(user.Email, user.Username, passwordHash);
}
user.PasswordHash = passwordHash;
}
public async Task<string> GetPasswordHashAsync(Login user, CancellationToken cancellationToken)
{
return await Task.FromResult(user.PasswordHash);
}
public async Task<bool> HasPasswordAsync(Login user, CancellationToken cancellationToken)
{
return await Task.FromResult(!string.IsNullOrEmpty(user.PasswordHash) && !string.IsNullOrEmpty(user.Salt));
}
public Task SetEmailAsync(Login user, string email, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetEmailAsync(Login user, CancellationToken cancellationToken)
{
return Task.FromResult(user.Email);
}
public async Task<bool> GetEmailConfirmedAsync(Login user, CancellationToken cancellationToken)
{
return await Task.FromResult(user.EmailConfirmed);
}
public Task SetEmailConfirmedAsync(Login user, bool confirmed, CancellationToken cancellationToken)
{
return Task.FromResult(user.EmailConfirmed = confirmed);
}
public Task<Login> FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetNormalizedEmailAsync(Login user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task SetNormalizedEmailAsync(Login user, string normalizedEmail, CancellationToken cancellationToken)
{
return Task.FromResult(user.Email = normalizedEmail.ToLower());
}
public Task SetPhoneNumberAsync(Login user, string phoneNumber, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetPhoneNumberAsync(Login user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<bool> GetPhoneNumberConfirmedAsync(Login user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task SetPhoneNumberConfirmedAsync(Login user, bool confirmed, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
Startup.cs ConfigureServices方法:
services.AddSingleton<IUserStore<Login>, UserStore>();
答案 1 :(得分:0)
我最接近的答案就是这个git项目:https://github.com/grandchamp/Identity.Dapper
它仍在进行中,我正在与项目所有者合作进行一些改进,但对于那些偶然发现这个问题的人来说,现在项目是你最好的选择。