developer tip

Microsoft.AspNet.Identity.EntityFramework.IdentityUser에서 ID 유형을 변경하는 방법

copycodes 2020. 11. 15. 11:26
반응형

Microsoft.AspNet.Identity.EntityFramework.IdentityUser에서 ID 유형을 변경하는 방법


(ASP.NET MVC 5, EF6, VS2013)

유형에서 "Id"필드 의 유형 을 문자열에서 int변경하는 방법을 알아 내려고 합니다.

Microsoft.AspNet.Identity.EntityFramework.IdentityUser

새 사용자 계정이 GUID가 아닌 정수 ID와 연결되도록하기 위해. 그러나 이것은 파생 된 사용자 클래스에 int 유형의 새 Id 속성을 단순히 추가하는 것보다 더 복잡해 보입니다. 이 메소드 서명을 살펴보십시오.

(어셈블리 Microsoft.AspNet.Identity.Core.dll에서)

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

따라서 userId가 문자열이어야하는 ASP.NET ID 프레임 워크에 구워진 다른 메서드가있는 것 같습니다. 이 클래스도 다시 구현해야합니까?

사용자 테이블의 ID에 대한 GUID를 저장하지 않는 이유에 대한 설명 :

-외래 키를 통해 데이터를 사용자 테이블에 연결하는 다른 테이블이 있습니다. (사용자가 사이트에 콘텐츠를 저장할 때) 더 큰 필드 유형을 사용하고 명확한 이점없이 추가 데이터베이스 공간을 사용할 이유가 없습니다. (GUID와 int ID 사용에 대한 다른 게시물이 있다는 것을 알고 있지만 많은 사람들이 int ID가 더 빠르고 공간을 적게 사용한다고 제안하는 것처럼 보이므로 여전히 궁금합니다.)

-사용자가 특정 사용자에 대한 데이터를 검색 할 수 있도록 편안한 엔드 포인트를 노출 할 계획입니다. 나는 생각한다 :

/users/123/name

보다 깨끗하다

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

ASP.NET 팀이 이러한 방식으로 ID를 구현하기로 결정한 이유를 아는 사람이 있습니까? 이것을 int 유형으로 변경하려고 시도하는 데 시력이 부족합니까? (아마 내가 놓친 혜택이있을 수 있습니다.)

감사...

-벤


따라서 int ID를 원하는 경우 고유 한 POCO IUser 클래스를 만들고 1.0 RTM 릴리스에서 사용자 지정 IUser 클래스에 대한 IUserStore를 구현해야합니다.

이것은 우리가 지원할 시간이 없었지만 지금은 1.1에서 이것을 쉽게 만드는 방법을 찾고 있습니다. 조만간 야간 빌드에서 무언가를 사용할 수 있기를 바랍니다.

1.1-alpha1 예제로 업데이트 됨 : 야간 빌드를 얻는 방법

최신 야간 비트로 업데이트하는 경우 지금 더 쉽게 만들 수있는 새로운 1.1-alpha1 API를 사용해 볼 수 있습니다. 예를 들어 문자열 대신 Guid를 연결하는 방법은 다음과 같습니다.

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

사용 스테판 Cebulak 의 대답과 벤 포스터의 멋진 블로그 기사 베어 박탈 ASP.NET 신원 I 되세요 내가 ASP.NET 정체성에 적용한 다음 솔루션을 내놓았다 2.0 비주얼 스튜디오 2013에 의해 생성 된로 AccountController.

이 솔루션은 정수를 사용자의 기본 키로 사용하고 데이터베이스로 이동하지 않고도 현재 로그인 한 사용자의 ID를 가져올 수 있습니다.

다음 단계를 따르십시오.

1. 사용자 지정 사용자 관련 클래스 만들기

기본적 으로는 기본 키 유형으로를 AccountController사용하는 클래스를 사용 string합니다. 대신를 사용하는 아래 클래스를 만들어야합니다 int. 아래의 모든 클래스를 하나의 파일에 정의했습니다.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> { }

사용자 ID를 쉽게 노출 할 수있는 사용자 지정 ClaimsPrincipal을 사용하는 것도 유용합니다.

public class AppClaimsPrincipal : ClaimsPrincipal
{
    public AppClaimsPrincipal( ClaimsPrincipal principal ) : base( principal )
    { }

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

2. 사용자 지정 만들기 IdentityDbContext

우리 애플리케이션의 데이터베이스 컨텍스트는 IdentityDbContext기본적으로 모든 인증 관련 DbSet를 구현하는 확장됩니다 . DbContext.OnModelCreating빈 메서드 인 경우에도에 대해 잘 모르겠 IdentityDbContext.OnModelCreating으므로 재정의 할 때 다음을 호출해야합니다.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
    }
}

사용자 정의를 작성합니다 UserStoreUserManager이상 사용할 것이다,

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. AccountController사용자 정의 클래스를 사용하도록 수정

모든 변경 UserManagerAppUserManager, UserStoreAppUserStore등이 생성자의 예를 보자

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

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

5. ClaimIdentity쿠키 저장 하기 위해 사용자 ID를 클레임으로 추가

1 단계에서는 AppClaimsPrincipal에서 가져온 UserId를 노출하는 을 만들었습니다 ClaimType.Sid. 그러나이 클레임을 사용할 수 있으려면 사용자 로그인시 추가해야합니다. 에서 방법. 로그인 할 책임이 우리는 주장을 추가,이 방법에 한 줄을 추가해야합니다.AccountControllerSingInAsync

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. BaseControllerCurrentUser특성

컨트롤러에서 현재 로그인 된 사용자의 ID에 쉽게 액세스하려면 BaseController컨트롤러가 파생 될 추상을 만드 십시오. 에서 다음과 같이 BaseController만듭니다 CurrentUser.

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


    public BaseController()
    {

    }
}

7. 컨트롤러 상속 BaseController및 즐기기

이제부터 CurrentUser.UserId컨트롤러에서를 사용하여 데이터베이스로 이동하지 않고도 현재 로그인 한 사용자의 ID에 액세스 할 수 있습니다 . 이를 사용하여 사용자에게 속한 개체 만 쿼리 할 수 ​​있습니다.

You don't have to take care of auto generation of user primary keys - no surprise, Entity Framework by default uses Identity for integer primary keys, when creating tables.

Warning! Keep in mind, that if you implement it in already released project, for already logged in users ClaimsType.Sid will not exist and FindFirst will return null in AppClaimsPrincipal. You need to either force logout all users or handle this scenario in AppClaimsPrincipal


@HaoKung

I've succeeded to make int id's with your nightly builds. User.Identity.GetUserId() problem is still there, but i just did int.parse() for now.

The biggest suprise was that i did not need to create ID by myself, db was made with identity id and it was somehow automatically set for new users 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)
    {
    }
}

Controller:

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

Hope release build will come soon :D...

P.S. Can't write comments so i did an answer, sorry.


As stated here:

In Visual Studio 2013, the default web application uses a string value for the key for user accounts. ASP.NET Identity enables you to change the type of the key to meet your data requirements. For example, you can change the type of the key from a string to an integer.

This topic on the above link shows how to start with the default web application and change the user account key to an integer. You can use the same modifications to implement any type of key in your project. It shows how to make these changes in the default web application, but you could apply similar modifications to a customized application. It shows the changes needed when working with MVC or Web Forms.


Basically you have to :

-Change the type of the key to int in the Identity user class
-Add customized Identity classes that use int as key
-Change the context class and user manager to use int as key
-Change start-up configuration to use int as key
-Change the AccountController to pass int as key

here is link where all steps are explained to achieve this.

참고URL : https://stackoverflow.com/questions/19553424/how-to-change-type-of-id-in-microsoft-aspnet-identity-entityframework-identityus

반응형