Tách ASP.NET IdentityUser khỏi các thực thể khác của tôi


11

Tôi có một ProjectName.Corethư viện chứa tất cả logic kinh doanh của tôi và các thực thể của tôi và hành vi của họ. Hiện tại không có bất kỳ mối quan hệ nào với Entity Framework hoặc bất kỳ DAL nào khác vì tôi muốn giữ những thứ đó tách biệt. Các cấu hình Entity Framework (sử dụng API Fluent) nằm trong một ProjectName.Infrastructuredự án để đảm bảo đẩy các thực thể của tôi vào EF. Về cơ bản, tôi đang đi theo hướng kiến ​​trúc giống như Hành.

Tuy nhiên, khi thêm khung nhận dạng ASP.NET vào hỗn hợp, tôi phải làm cho ApplicationUserthực thể của mình kế thừa từ IdentityUserlớp nhưng ApplicationUserlớp của tôi có quan hệ với các thực thể khác. Kế thừa từ việc IdentityUsertôi giới thiệu một tham chiếu đến Entity Framework trong dự án thực thể của tôi, một nơi mà tôi không muốn làm như vậy. Việc kéo ApplicationUserlớp ra khỏi dự án thực thể và vào Infrastructuredự án (vì nó đang sử dụng hệ thống nhận dạng dựa trên Entity Framework) sẽ dẫn đến các tham chiếu vòng tròn, do đó, đó không phải là cách để đi.

Có cách nào khác để tôi có thể giữ tách biệt giữa hai lớp bên cạnh việc không sử dụng ASP.NET Identity không?


1
Bạn có thể không tạo giao diện IApplicationUser trong dự án Core của mình và tiếp tục triển khai trong Cơ sở hạ tầng không? Theo tôi, trừ khi bạn đang tạo API hoặc bạn cần trao đổi việc triển khai giao diện khi chạy, chỉ cần giữ tất cả mã không phải UI của bạn trong một dự án. Có một loạt các dự án khác nhau chỉ làm tăng thêm chi phí quản lý tinh thần và mã của bạn mà không có nhiều lợi ích.
chết

Câu trả lời:


12

Bạn có thể tạo một lớp Người dùng không liên quan gì đến ASP.NET Identity trong thư viện lõi của bạn.

public class User {
    public Guid UserId { get; set; }
    public string UserName { get; set; }
    public string EmailAddress { get; set; }
    public string EmailAddressConfirmed { get; set; }
    public string PhoneNumber { get; set; }
    public string PhoneNumberConfirmed { get; set; }
    public string PasswordHash { get; set; }
    public string SecurityStamp { get; set; }

    ...

    public virtual ICollection<Role> Roles { get; set; }
    public virtual ICollection<UserClaim> UserClaims { get; set; }
    public virtual ICollection<UserLogin> UserLogins { get; set; }
}

Nếu bạn đang sử dụng Entity Framework, hãy tạo một lớp cấu hình cho các thực thể của bạn (tùy chọn).

internal class UserConfiguration : EntityTypeConfiguration<User>
{
    internal UserConfiguration()
    {
        ToTable("User");

        HasKey(x => x.UserId)
            .Property(x => x.UserId)
            .HasColumnName("UserId")
            .HasColumnType("uniqueidentifier")
            .IsRequired();

        Property(x => x.PasswordHash)
            .HasColumnName("PasswordHash")
            .HasColumnType("nvarchar")
            .IsMaxLength()
            .IsOptional();

        Property(x => x.SecurityStamp)
            .HasColumnName("SecurityStamp")
            .HasColumnType("nvarchar")
            .IsMaxLength()
            .IsOptional();

        Property(x => x.UserName)
            .HasColumnName("UserName")
            .HasColumnType("nvarchar")
            .HasMaxLength(256)
            .IsRequired();

        // EmailAddress, PhoneNumber, ...

        HasMany(x => x.Roles)
            .WithMany(x => x.Users)
            .Map(x =>
            {
                x.ToTable("UserRole");
                x.MapLeftKey("UserId");
                x.MapRightKey("RoleId");
            });

        HasMany(x => x.UserClaims)
            .WithRequired(x => x.User)
            .HasForeignKey(x => x.UserId);

        HasMany(x => x.UserLogins)
            .WithRequired(x => x.User)
            .HasForeignKey(x => x.UserId);
    }
}

Bạn cũng phải tạo các lớp cho Vai trò, UserClaim và UserLogin . Bạn có thể đặt tên cho chúng bất cứ thứ gì bạn chọn nếu bạn không thích những cái tên trên.

Trong lớp web, tạo một lớp có tên là AppUser (Hoặc tên khác nếu bạn chọn). Lớp này nên thực hiện các ASP.NET nhận dạng IUser <TKey> giao diện, nơi TKey là kiểu dữ liệu cho các khóa chính ( Guid trong ví dụ trên).

public class AppUser : IUser<Guid>
{
    public AppUser()
    {
        this.Id = Guid.NewGuid();
    }

    public AppUser(string userName)
        : this()
    {
        this.UserName = userName;
    }

    public Guid Id { get; set; }
    public string UserName { get; set; }
    public string EmailAddress { get; set; }
    public string EmailAddressConfirmed { get; set; }
    public string PhoneNumber { get; set; }
    public string PhoneNumberConfirmed { get; set; }
    public string PasswordHash { get; set; }
    public string SecurityStamp { get; set; }
}

Thay đổi tất cả các tham chiếu đến UserManager trong dự án web thành UserManager <AppUser, Guid> .

Cuối cùng, tạo UserStore của riêng bạn . Về cơ bản, UserStore tùy chỉnh sẽ lấy đối tượng AppUser , chuyển đổi nó thành đối tượng thực thể Người dùng , sau đó duy trì nó. Một ví dụ về một trong những phương pháp này được hiển thị dưới đây:

public class UserStore : 
    IUserLoginStore<AppUser, Guid>, 
    IUserClaimStore<AppUser, Guid>, 
    IUserRoleStore<AppUser, Guid>, 
    IUserPasswordStore<AppUser, Guid>, 
    IUserSecurityStampStore<AppUser, Guid>, 
    IUserStore<AppUser, Guid>, 
    IDisposable
{
    private User MapFromAppUser(AppUser appUser)
    {
        if (appUser == null)
            return null;

        var userEntity = new User();

        PopulateUser(userEntity, appUser);

        return userEntity;
    }

    private void PopulateUser(User user, AppUser appUser)
    {
        user.UserId = appUser.Id;
        user.UserName = appUser.UserName;
        user.EmailAddress = appUser.EmailAddress;
        user.EmailAddressConfirmed = appUser.EmailAddressConfirmed;
        user.PhoneNumber = appUser.PhoneNumber;
        user.PhoneNumberConfirmed = appUser.PhoneNumberConfirmed;
        user.PasswordHash = appUser.PasswordHash;
        user.SecurityStamp = appUser.SecurityStamp;

        // First name, last name, ... 
    }

    #region IUserStore<AppUser, Guid> Members

    public Task CreateAsync(AppUser appUser)
    {
        if (appUser == null)
            throw new ArgumentNullException("appUser");

        var userEntity = MapFromAppUser(appUser);

        // Persist the user entity to database using a data repository.
        // I'll leave this to you.
    }

    ...

    #endregion
}

Để có được một mô tả đầy đủ về một triển khai có thể, bấm vào đây .

Cuối cùng, đó là sự lựa chọn của bạn. Đo lường số lượng nỗ lực mà bạn cần để duy trì việc triển khai này thay vì chỉ tham khảo khung Nhận dạng trong thư viện Core của bạn. Cá nhân, tôi đã nghĩ làm theo cách mà tôi đã mô tả ở trên, tuy nhiên, tôi đã không làm vì tôi có khả năng phải thay đổi mã của mình mỗi khi cập nhật khung nhận dạng ASP.NET.

Hy vọng điều này sẽ giúp và trả lời câu hỏi của bạn!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.