デフォルトでは、ASP.NET IdentityのデータプロバイダーはMSSQLですが、Identity認証システムは他のリレーショナルDBMSと対話できるため、InterSystemsCachéのこの機能を調査して実装しました。
まず、これは何のためですか? プロジェクトで.NET上のCachéDBMSを使用し、完全で信頼性の高い認証システムが必要だと想像してください。 もちろん、このようなシステムを手作業でゼロから作成することは非常に非現実的であり、.NET-ASP.NET Identityの既存のアナログを使用する必要があります。 しかし、その純粋な形式では、フレームワークはネイティブのMicrosoft DBMS-MS SQLでのみ機能します。 私たちのタスクは、わずかな手を動かすだけでIdentityをシステム間キャッシュDBMSに移植できるアダプターを実装することでした。 タスクは、ASP.NET IdentityCachéプロバイダーに実装されました。
ASP.NET IdentityCachéプロバイダープロジェクトの本質は、ASP.NET IdenityのCachéデータプロバイダーを実装することです。 主なタスクは、テーブルAspNetRoles 、 AspNetUserClaims 、 AspNetUserLogins 、 AspNetUserRoles 、およびAspNetUsersを 格納し 、 それらへのアクセスを提供することでした 。これらのテーブルを操作する標準ロジックに違反することはありませんでした 。
ASP.NET IDアーキテクチャに関するいくつかの言葉
Asp.Net Identityの主要なオブジェクトは、ユーザーとロールです。 ユーザーを作成および削除し、ユーザーリポジトリと対話するためのすべての機能は、 UserManagerクラスに格納されます。 ロールを使用して管理するには、Asp.Net IdentityでRoleManagerクラスを定義します。 以下は、Microsoft.AspNet.Identity.Coreクラス図です。
UserManagerの各ユーザーは、 IUserインターフェイスオブジェクトを提供します 。 同時に、すべてのユーザー管理操作は、 IUserStoreオブジェクトによって表されるストレージを介して実行されます。 各役割はIRoleインターフェイスの実装を表し、役割の操作(追加、変更、削除)はRoleManagerを使用して実行されます。 IUser 、 IRole 、 IUserStore 、およびIRoleStoreインターフェースの直接実装は、Microsoft.AspNet.Identity EntityFramework名前空間を提供します。ここでは、 IdentityUser 、 UserStore 、 IdentityRole 、 RoleStore 、 IdentityDbContextなどのクラスを使用できます。
デフォルトで指定されたテーブルにないユーザーに関する追加情報を保存する必要がある場合、 IdentityUserClaimクラス(ホールマーク)があります。これにより、ユーザーの登録などに必要なフィールドを追加して使用できます。
UserManagerの各ユーザーは、 IUserインターフェイスオブジェクトを提供します 。 同時に、すべてのユーザー管理操作は、 IUserStoreオブジェクトによって表されるストレージを介して実行されます。 各役割はIRoleインターフェイスの実装を表し、役割の操作(追加、変更、削除)はRoleManagerを使用して実行されます。 IUser 、 IRole 、 IUserStore 、およびIRoleStoreインターフェースの直接実装は、Microsoft.AspNet.Identity EntityFramework名前空間を提供します。ここでは、 IdentityUser 、 UserStore 、 IdentityRole 、 RoleStore 、 IdentityDbContextなどのクラスを使用できます。
デフォルトで指定されたテーブルにないユーザーに関する追加情報を保存する必要がある場合、 IdentityUserClaimクラス(ホールマーク)があります。これにより、ユーザーの登録などに必要なフィールドを追加して使用できます。
ASP.NET IdentityのCachéデータプロバイダの実装に進みましょう。 次の2段階で行われました。
-データストレージクラス(状態の格納を担当)とIdentityDbContextクラスの実装。これは、データウェアハウスを操作するためのすべての低レベルロジックをカプセル化します。 IdentityDbInitializerクラスも実装され、CachéデータベースをIdentityで動作するように適合させました。
-UserStoreおよびRoleStoreクラスの実装(統合とともに)
テスト)。 デモンストレーションプロジェクト。
最初の段階で、次のクラスが実装されました。
-IdentityUser - IUserインターフェイスの実装。
-IdentityUserRole-ユーザー-ロール通信の関連エンティティ。
-IdentityUserLogin-ユーザーのログインに関するデータ。
UserLoginInfoクラスの拡張可能なバージョン。
-IdentityUserClaim-ユーザーのブランド情報。
-IdentityDbContext <TUser、TRole、TKey、TUserLogin、TUserRole、TUserClaim>-Entity Frameworkデータベースコンテキスト。
IdentityUserのIDをより詳細に検討します。これは、ユーザー、ロール、ログイン、ブランド、およびユーザーとロールの関係のリポジトリです。 IdentityUserの共通および汎用バージョンの実装例。
namespace InterSystems.AspNet.Identity.Cache { /// <summary> /// IUser implementation /// </summary> public class IdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUser { /// <summary> /// Constructor which creates a new Guid for the Id /// </summary> public IdentityUser() { Id = Guid.NewGuid().ToString(); } /// <summary> /// Constructor that takes a userName /// </summary> /// <param name="userName"></param> public IdentityUser(string userName) : this() { UserName = userName; } } /// <summary> /// IUser implementation /// </summary> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TLogin"></typeparam> /// <typeparam name="TRole"></typeparam> /// <typeparam name="TClaim"></typeparam> public class IdentityUser<TKey, TLogin, TRole, TClaim> : IUser<TKey> where TLogin : IdentityUserLogin<TKey> where TRole : IdentityUserRole<TKey> where TClaim : IdentityUserClaim<TKey> { /// <summary> /// Constructor /// </summary> public IdentityUser() { Claims = new List<TClaim>(); Roles = new List<TRole>(); Logins = new List<TLogin>(); } /// <summary> /// Email /// </summary> public virtual string Email { get; set; }
Identityにアクセス権の制限を実装するために、特別なオブジェクト(ロール)が設計されています。 構成内のロールは、さまざまなユーザーグループのロールまたはアクティビティに対応する場合があります。
namespace InterSystems.AspNet.Identity.Cache { /// <summary> /// EntityType that represents a user belonging to a role /// </summary> public class IdentityUserRole : IdentityUserRole<string> { } /// <summary> /// EntityType that represents a user belonging to a role /// </summary> /// <typeparam name="TKey"></typeparam> public class IdentityUserRole<TKey> { /// <summary> /// UserId for the user that is in the role /// </summary> public virtual TKey UserId { get; set; } /// <summary> /// RoleId for the role /// </summary> public virtual TKey RoleId { get; set; } } }
IdentityDbContext-接続の作成をカプセル化するエンティティ。データベースからエンティティをロードし、ユーザーオブジェクトと関連テーブルおよびフィールド値の構造との対応を検証します。 例として、ID要件に従ってテーブルを検証するOnModelCreatingメソッドを考えます。
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Mapping and configuring identity entities according to the Cache tables var user = modelBuilder.Entity<TUser>() .ToTable("AspNetUsers"); user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId); user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId); user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId); user.Property(u => u.UserName) .IsRequired() .HasMaxLength(256) .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("UserNameIndex") { IsUnique = true })); user.Property(u => u.Email).HasMaxLength(256); modelBuilder.Entity<TUserRole>() .HasKey(r => new { r.UserId, r.RoleId }) .ToTable("AspNetUserRoles"); modelBuilder.Entity<TUserLogin>() .HasKey(l => new { l.LoginProvider, l.ProviderKey, l.UserId }) .ToTable("AspNetUserLogins"); modelBuilder.Entity<TUserClaim>() .ToTable("AspNetUserClaims"); var role = modelBuilder.Entity<TRole>() .ToTable("AspNetRoles"); role.Property(r => r.Name) .IsRequired() .HasMaxLength(256) .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("RoleNameIndex") { IsUnique = true })); role.HasMany(r => r.Users).WithRequired().HasForeignKey(ur => ur.RoleId); }
DbModelBuilderは、CLRクラスをデータベーススキーマにマップするために使用されます。 EDMモデルを構築するこのコードベースのアプローチは、コードファーストと呼ばれます。 DbModelBuilderは通常、 OnModelCreating(DbModelBuilder)をオーバーライドしてモデルをカスタマイズするために使用されます。 ただし、 DbModelBuilderをDbContextから独立して使用してモデルを構築し、 DbContextまたはObjectContextを構築することもできます 。
IdentityDbInitializerクラスは、 Identityで使用するCachéデータベースを準備します。
public void InitializeDatabase(DbContext context) { using (var connection = BuildConnection(context)) { var tables = GetExistingTables(connection); CreateTableIfNotExists(tables, AspNetUsers, connection); CreateTableIfNotExists(tables, AspNetRoles, connection); CreateTableIfNotExists(tables, AspNetUserRoles, connection); CreateTableIfNotExists(tables, AspNetUserClaims, connection); CreateTableIfNotExists(tables, AspNetUserLogins, connection); CreateIndexesIfNotExist(connection); } }
CreateTableIfNotExistsメソッドは、必要なテーブルを作成します(まだ存在しない場合)。 テーブルの存在の確認は、既存のテーブルに関する情報を保存するCacheテーブル-Dictionary.CompiledClassにクエリを実行することで行われます。 テーブルがまだ作成されていない場合は、作成されます。
第2段階では、IdentityUserStoreやIdentityRoleStoreなどのエンティティが実装され、ユーザーとロールの追加、編集、削除のロジックがカプセル化されます。 これらのエンティティには、単体テストで100%のカバレッジが必要でした。
要約すると、ASP.NET IdentityテクノロジーのコンテキストでEntity Frameworkを使用してCachéDBMSを操作するためのデータプロバイダーを実装しました。 アプリケーションは別のNugetパッケージで設計されており、必要に応じてCachéDBMSで動作し、同時に標準のMicrosoft認証を使用するので、Nuget Package Managerを介してIdentityCachéプロバイダーアセンブリをプロジェクトに実装するだけで十分です。
ソースコード、サンプル、およびテストを含むプロジェクトの実装は、 GitHubで入手できます 。