Jak zmienić typ id w Microsoft.AspNet.Tożsamość./ Align = "left" / Identity

(ASP.NET MVC 5, EF6, VS2013)

Próbuję dowiedzieć się, jak zmienić typ pola " Id " z string na int w typie:

Microsoft.AspNet.Identity.EntityFramework.IdentityUser

Aby nowe konta użytkowników były powiązane z identyfikatorem całkowitym, a nie z identyfikatorem GUID. Ale wydaje się, że będzie to bardziej skomplikowane niż po prostu dodanie nowej właściwości Id z typem int w mojej pochodnej klasie użytkownika. Spójrz na podpis tej metody:

(ze Zgromadzenia Microsoft.AspNet.Tożsamość.Rdzeń.dll)

public class UserManager<TUser> : IDisposable where TUser : global::Microsoft.AspNet.Identity.IUser
  {
  ...
  public virtual Task<IdentityResult> AddLoginAsync(string userId, UserLoginInfo login);
  ...
  }

Wydaje się więc, że istnieją inne metody pieczenia w ASP.NET Framework tożsamości, które wymagają, aby userId był ciągiem znaków. Czy muszę ponownie wdrożyć te zajęcia?

Wyjaśnienie dlaczego nie chcę przechowywać identyfikatorów GUID w tabeli użytkownika:

- pojawią się inne tabele, które odnoszą dane do tabeli users za pomocą klucza obcego. (Kiedy użytkownicy zapisują treści na stronie.) Nie widzę powodu, aby używać większych wpisz pole i spędź dodatkową przestrzeń bazy danych bez wyraźnych zalet. (Wiem, że istnieją inne posty na temat korzystania GUIDs vs int ids, ale wydaje się, że wiele sugeruje, że INT ids są szybsze i zużywają mniej miejsca, co wciąż pozostawia mnie zastanawiasz.)

-planuję ujawnić restful endpoint, aby umożliwić użytkownikom pobieranie danych o konkretnym użytkowniku. Myślę:

/users/123/name

Jest czystsza niż

/users/{af54c891-69ba-4ddf-8cb6-00d368e58d77}/name

Czy ktoś wie dlaczego ASP.NET zespół zdecydował się wdrożyć ID w ten sposób? Czy jestem niski widziany w próbie zmiany tego na typ int? (Być może brakuje mi korzyści.)

Dzięki...

- Ben

Author: BenjiFB, 2013-10-24

5 answers

Więc jeśli chcesz ID int, musisz utworzyć własną klasę POCO IUser i zaimplementować IUserStore dla swojej niestandardowej klasy IUSER w wydaniu 1.0 RTM.

To jest coś, czego nie mieliśmy czasu na wsparcie, ale zamierzam teraz ułatwić to (ier) w wersji 1.1. Mam nadzieję, że wkrótce coś będzie dostępne w nocnych kompilacjach.

Aktualizacja z przykładem 1.1-alpha1: Jak zdobyć nocne budowle

Jeśli zaktualizujesz do najnowszych bitów nocnych, możesz wypróbuj nowe interfejsy API 1.1-alpha1, które powinny to teraz ułatwić: Oto, jak powinno wyglądać Podłączanie GUID zamiast ciągów, na przykład

    public class GuidRole : IdentityRole<Guid, GuidUserRole> { 
        public GuidRole() {
            Id = Guid.NewGuid();
        }
        public GuidRole(string name) : this() { Name = name; }
    }
    public class GuidUserRole : IdentityUserRole<Guid> { }
    public class GuidUserClaim : IdentityUserClaim<Guid> { }
    public class GuidUserLogin : IdentityUserLogin<Guid> { }

    public class GuidUser : IdentityUser<Guid, GuidUserLogin, GuidUserRole, GuidUserClaim> {
        public GuidUser() {
            Id = Guid.NewGuid();
        }
        public GuidUser(string name) : this() { UserName = name; }
    }

    private class GuidUserContext : IdentityDbContext<GuidUser, GuidRole, Guid, GuidUserLogin, GuidUserRole, GuidUserClaim> { }
    private class GuidUserStore : UserStore<GuidUser, GuidRole, Guid, GuidUserLogin, GuidUserRole, GuidUserClaim> {
        public GuidUserStore(DbContext context)
            : base(context) {
        }
    }
    private class GuidRoleStore : RoleStore<GuidRole, Guid, GuidUserRole> {
        public GuidRoleStore(DbContext context)
            : base(context) {
        }
    }

    [TestMethod]
    public async Task CustomUserGuidKeyTest() {
        var manager = new UserManager<GuidUser, Guid>(new GuidUserStore(new GuidUserContext()));
        GuidUser[] users = {
            new GuidUser() { UserName = "test" },
            new GuidUser() { UserName = "test1" }, 
            new GuidUser() { UserName = "test2" },
            new GuidUser() { UserName = "test3" }
            };
        foreach (var user in users) {
            UnitTestHelper.IsSuccess(await manager.CreateAsync(user));
        }
        foreach (var user in users) {
            var u = await manager.FindByIdAsync(user.Id);
            Assert.IsNotNull(u);
            Assert.AreEqual(u.UserName, user.UserName);
        }
    }
 30
Author: Hao Kung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-12 18:01:09

Używając odpowiedzi Stefana Cebulakai wspaniałego artykułu na blogu Bena Fostera ASP.NET Identity Stripped Bare wymyśliłem poniżej rozwiązanie, które zastosowałem do ASP.NET tożsamość 2.0 z wygenerowanym przez Visual Studio 2013 AccountController.

Rozwiązanie wykorzystuje liczbę całkowitą jako klucz podstawowy dla użytkowników, a także pozwala uzyskać identyfikator aktualnie zalogowanego użytkownika bez konieczności przechodzenia do bazy danych.

Oto kroki, musisz follow:

1. Tworzenie niestandardowych klas związanych z użytkownikiem

Domyślnie AccountController używa klas, które używają string jako typu klucza podstawowego. Musimy utworzyć poniżej klasy, które zamiast tego użyją int. Zdefiniowałem wszystkie poniższe klasy w jednym pliku: AppUser.cs

public class AppUser :
    IdentityUser<int, AppUserLogin, AppUserRole, AppUserClaim>,
    IUser<int>
{

}

public class AppUserLogin : IdentityUserLogin<int> { }

public class AppUserRole : IdentityUserRole<int> { }

public class AppUserClaim : IdentityUserClaim<int> { }

public class AppRole : IdentityRole<int, AppUserRole> { }
Przydatne będzie również posiadanie niestandardowego ClaimsPrincipal, który z łatwością ujawni identyfikator użytkownika.]}
public class AppClaimsPrincipal : ClaimsPrincipal
{
    public AppClaimsPrincipal( ClaimsPrincipal principal ) : base( principal )
    { }

    public int UserId
    {
        get { return int.Parse(this.FindFirst( ClaimTypes.Sid ).Value); }
    }
}

2. Tworzenie niestandardowego IdentityDbContext

Kontekst bazy danych naszej aplikacji będzie extend IdentityDbContext, który domyślnie implementuje wszystkie zestawy Dbsetów związane z uwierzytelnieniem. Nawet jeśli DbContext.OnModelCreating jest metodą pustą, nie jestem pewien co do IdentityDbContext.OnModelCreating, więc przy nadpisywaniu pamiętaj o wywołaniu base.OnModelCreating( modelBuilder ) AppDbContext.cs

public class AppDbContext :
    IdentityDbContext<AppUser, AppRole, int, AppUserLogin, AppUserRole, AppUserClaim>
{
    public AppDbContext() : base("DefaultConnection")
    {
        // Here use initializer of your choice
        Database.SetInitializer( new CreateDatabaseIfNotExists<AppDbContext>() );
    }


    // Here you define your own DbSet's



    protected override void OnModelCreating( DbModelBuilder modelBuilder )
    {
        base.OnModelCreating( modelBuilder );

        // Here you can put FluentAPI code or add configuration map's
    }
}

3. Utwórz własne UserStore i UserManager, które użyją powyższego

AppUserStore.cs

public interface IAppUserStore : IUserStore<AppUser, int>
{

}

public class AppUserStore :
    UserStore<AppUser, AppRole, int, AppUserLogin, AppUserRole, AppUserClaim>,
    IAppUserStore
{
    public AppUserStore() : base( new AppDbContext() )
    {

    }

    public AppUserStore(AppDbContext context) : base(context)
    {

    }
}

AppUserManager.cs

public class AppUserManager : UserManager<AppUser, int>
{
    public AppUserManager( IAppUserStore store ) : base( store )
    {

    }
}

4. Modyfikuj AccountController, aby używać własnych klas

Zmień wszystkie UserManager na AppUserManager, UserStore do AppUserStore itd. Weźmy na przykład konstruktorzy:

public AccountController()
    : this( new AppUserManager( new AppUserStore( new AppDbContext() ) ) )
{
}

public AccountController(AppUserManager userManager)
{
    UserManager = userManager;
}

5. Pliki cookies wykorzystywane są w celu:]} W kroku 1 utworzyliśmy AppClaimsPrincipal, który wyświetla identyfikator UserId usunięty z ClaimType.Sid. Aby jednak to roszczenie było dostępne, musimy je dodać, podczas logowania użytkownika. W AccountController za logowanie odpowiada metoda SingInAsync. Musimy dodać linię do tej metody, aby dodać twierdzenie.
private async Task SignInAsync(AppUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    ClaimsIdentity identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

    // Extend identity claims
    identity.AddClaim( new Claim( ClaimTypes.Sid, user.Id.ToString() ) );

    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}

6. Tworzenie BaseController z CurrentUser właściwością

Aby mieć łatwy dostęp do aktualnie zalogowanego w ID użytkownika w kontrolerach Utwórz abstrakcję BaseController, z której będą wywodzić się kontrolerzy. W BaseController Utwórz CurrentUser w następujący sposób:

public abstract class BaseController : Controller
{
    public AppClaimsPrincipal CurrentUser
    {
        get { return new AppClaimsPrincipal( ( ClaimsPrincipal )this.User ); }
    }


    public BaseController()
    {

    }
}

7. Odziedzicz Kontrolery z BaseController i ciesz się

Od teraz możesz używać CurrentUser.UserId w swoich kontrolerach, aby uzyskać dostęp do identyfikatora aktualnie zalogowanego użytkownika bez podróży do bazy danych. Można go używać do odpytywania tylko obiektów, które należą do użytkownika.

Nie musisz dbać o Automatyczne generowanie użytkownika klucze-nic dziwnego, struktura Entity domyślnie używa tożsamości dla kluczy podstawowych integer, podczas tworzenia tabel.

Uwaga! pamiętaj, że jeśli zaimplementujesz go w już wydanym projekcie, dla już zalogowanych użytkowników ClaimsType.Sid nie będzie istnieć i FindFirst zwróci null w AppClaimsPrincipal. W tym celu musisz wymusić wylogowanie wszystkich użytkowników lub obsłużyć ten scenariusz w AppClaimsPrincipal

 52
Author: krzychu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:19

@ HaoKung

Udało mi się zrobić int id z Twoimi nocnymi budami. Użytkownik.Tożsamość.Problem z GetUserId() nadal istnieje, ale właśnie zrobiłem int.parse() na razie.

Największą niespodzianką było to,że nie musiałem sam tworzyć ID, db zostało wykonane z identity i jakoś automatycznie ustawione dla nowych użytkowników OO...

Model:

    public class ApplicationUser : IdentityUser<int, IntUserLogin, IntUserRole, IntUserClaim>
{
    public ApplicationUser()
    {
    }
    public ApplicationUser(string name) : this() { UserName = name; }
}

public class ApplicationDbContext : IntUserContext
{
    public ApplicationDbContext()
    {

    }
}

private class IntRole : IdentityRole<int, IntUserRole>
{
    public IntRole()
    {
    }
    public IntRole(string name) : this() { Name = name; }
}
private class IntUserRole : IdentityUserRole<int> { }
private class IntUserClaim : IdentityUserClaim<int> { }
private class IntUserLogin : IdentityUserLogin<int> { }
private class IntUserContext : IdentityDbContext<ApplicationUser, IntRole, int, IntUserLogin, IntUserRole, IntUserClaim>
{
    public IntUserContext()
        : base("DefaultConnection")
    {

    }
}
private class IntUserStore : UserStore<ApplicationUser, IntRole, int, IntUserLogin, IntUserRole, IntUserClaim>
{
    public IntUserStore(DbContext context)
        : base(context)
    {

    }
}
private class IntRoleStore : RoleStore<IntRole, int, IntUserRole>
{
    public IntRoleStore(DbContext context)
        : base(context)
    {
    }
}

Kontroler:

        public AccountController()
        : this(new UserManager<ApplicationUser, int>(new IntUserStore(new ApplicationDbContext())))
    {
    }

    public AccountController(UserManager<ApplicationUser, int> userManager)
    {
        UserManager = userManager;
    }

    public UserManager<ApplicationUser, int> UserManager { get; private set; }

Mam nadzieję, że release build już wkrótce: D...

P. S. nie mogę pisać komentarzy więc odpowiedziałem, przepraszam.

 6
Author: Stefan Cebulak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-02 02:37:07

W Visual Studio 2013 domyślna aplikacja internetowa używa wartości ciągu dla klucza dla kont użytkowników. ASP.NET tożsamość umożliwia zmianę typu klucza, aby spełnić wymagania dotyczące danych. Na przykład można zmienić typ klucza z ciągu znaków na liczbę całkowitą.

Http://www.asp.net/identity/overview/extensibility/change-primary-key-for-users-in-aspnet-identity

Ten temat na powyższym linku pokazuje jak zacząć od domyślnej aplikacji internetowej i Zmień klucz konta użytkownika na liczbę całkowitą. Możesz użyć tych samych modyfikacji, aby zaimplementować dowolny typ klucza w swoim projekcie. Pokazuje, jak wprowadzić te zmiany w domyślnej aplikacji internetowej, ale można zastosować podobne modyfikacje do niestandardowej aplikacji. Pokazuje zmiany potrzebne podczas pracy z MVC lub formularzami webowymi.

 4
Author: Manik Arora,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-02 19:19:41

W zasadzie musisz:

- Zmiana typu klucza na int w klasie Identity user
-Dodaj niestandardowe klasy tożsamości, które używają int jako klucza
-Zmień klasę kontekstową i menedżera użytkowników na Int jako klucz
-Zmień konfigurację uruchamiania, aby użyć int jako klucza
-Zmień AccountController, aby przekazać int jako klucz

Tutaj {[10] } jest link, gdzie wszystkie kroki są wyjaśnione, aby to osiągnąć.

 3
Author: lyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-29 09:37:45