.net核心身份没有使用int ID

时间:2017-03-03 22:29:10

标签: .net-core identity

我正在尝试使用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)。但是,如果我仔细观察,我会发现IUserStoreIRoleStoreMicrosoft.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

基于此我已经开始创建我自己的RoleManagerUserManager,这基本上只是扩展了身份版本:

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>>()
            ;

到目前为止一直很好......

2 个答案:

答案 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

它仍在进行中,我正在与项目所有者合作进行一些改进,但对于那些偶然发现这个问题的人来说,现在项目是你最好的选择。