2017-03-03 2 views
1

J'essaie de créer une solution .net Core en utilisant Identity sans EntityFramework mais avec des ID entiers (UserId et RoleId). J'ai suivi cette configuration de base pour créer la solution et enlever EF (https://taherchhabra.github.io/jekyll/update/2016/09/22/aspnet-core-identity-without-entityframework.html) mais ceci a toujours la colonne stupide d'identification de guide pour les utilisateurs. Lorsque je tente de changer je rencontre un problème dans la création de mon UserStore parce qu'il hérite de IUserStore<User> qui exige que je mets en œuvre.net Identité de base sans EntityFramework utilisant des identifiants int

Task<User> FindByIdAsync(string userId, CancellationToken cancellationToken)

qui ou bien sûr, la valeur Id est une chaîne au lieu d'un int. J'ai lu plusieurs choses sur la façon de changer les solutions EF pour utiliser ints et j'ai creusé dans la façon dont EF le fait, mais tout est basé sur des classes EF qui utilisent un TKey.

J'ai essayé de créer mon propre IUserStore pour changer les chaînes en ints mais le projet ne pourrait même pas tourner (il compilerait bien mais quand j'essayerais de l'exécuter localement il sortirait avant de terminer la rotation).

Est-ce que quelqu'un sait comment accomplir cela? J'ai beaucoup cherché et je ne trouve rien.

Edit: Ce que je l'ai fait jusqu'à présent est de créer mon propre UserStore et RollStore (qui sont essentiellement des copies des originaux que je vais modifier légèrement une fois que je me travaille). Dans mon HomeController j'ajouté ce qui suit:

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

} 

Ceci est essentiellement un « est-il branché » test que je peux parcourir dans le débogueur.

Dans mon Startup.cs:

services.AddSingleton<IUserStore<User>, UserStore>(); 
services.AddSingleton<IRoleStore<Role>, RoleStore>(); 

services.AddIdentity<User, Role>() 
    .AddDefaultTokenProviders(); 

Cela fait travailler (débogage dans mon point de terminaison, le user est correctement peuplée). Mais, si je regarde de près je me rends compte que IUserStore et IRoleStore sont les versions Microsoft.AspNetCore.Identity ce qui signifie que je suis toujours dépendante de ces contrats et je suis tenu d'utiliser le Guid pour un Id.

Si je force la question, en utilisant

services.AddSingleton<SandboxCoreDapper.Identity.Interfaces.IUserStore<User>, UserStore>(); 
services.AddSingleton<SandboxCoreDapper.Identity.Interfaces.IRoleStore<Role>, RoleStore>(); 

puis lorsque je tente de frapper mon point final, le UserManager ne parviendra pas à résoudre:

« Impossible de résoudre le service de type « Microsoft.AspNetCore. Identity.IUserStore 1[SandboxCoreDapper.Models.User]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager 1 [SandboxCoreDapper.Models.User] '. "

Edit 2 J'ai trouvé cette discussion intéressante: https://github.com/aspnet/Identity/issues/493

Sur la base que je suis allé de l'avant et créé mon propre RoleManager et UserManager qui essentiellement étendre simplement les versions d'identité:

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) 
     { 

     } 

    } 
} 

et de même pour RoleManager.

Puis j'ajouté à Startup.cs

services.AddIdentity<User, Role>() 
    .AddDefaultTokenProviders() 
    .AddUserManager<SandboxCoreDapper.Identity.Services.UserManager<User>>() 
    .AddRoleManager<SandboxCoreDapper.Identity.Services.RoleManager<Role>>() 
      ; 

So far so good ...

+0

essayez d'avoir un coup d'oeil à ceci: http://stackoverflow.com/questions/36184856/authentication-and-authorization-without-framework-in-asp-net-5-mvc-6 – ganders

+0

Merci @ganders. J'ai lu cette question mais je suis bloqué sur le "Vous pouvez utiliser le UserManager intégré si vous implémentez l'userstore et le rolestore, il n'est pas nécessaire de l'implémenter vous-même sauf si vous avez d'autres raisons de le faire." J'essaye de faire ceci mais le 'UserManager' continue de pointer vers l'identité par défaut' UserStore' et je n'arrive pas à comprendre comment le pointer vers ma propre version. Le seul article que je peux trouver sur le sujet est pour Identity 2 --pre Core – nurdyguy

+0

avez-vous enregistré votre UserStore dans le fichier startup.cs? – ganders

Répondre

0

Le plus proche que je pouvais venir à une réponse à cela est ce git projet: https://github.com/grandchamp/Identity.Dapper

Il est encore en cours et je travaille avec le propriétaire du projet sur certaines améliorations, mais pour tous ceux qui humbles sur cette question, dès maintenant ce projet est votre meilleur pari.

1

Ceci est en réponse à mon commentaire, et votre question/commentaire:

Il suffit de déclarer votre propre UserStore , puis enregistrez-le dans le Startup.cs.

Voilà ma mise en œuvre du UserStore pour accueillir ce scénario:

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

Et la méthode Startup.cs ConfigureServices:

services.AddSingleton<IUserStore<Login>, UserStore>(); 
+0

Je mets à jour ma question avec le point où je suis actuellement bloqué. – nurdyguy