User.Identity の利用可能なプロパティを拡張する方法 質問する

User.Identity の利用可能なプロパティを拡張する方法 質問する

私は、ユーザーが Web サイトにログインできるように MVC5 Identity 2.0 を使用しています。認証の詳細は SQL データベースに保存されます。Asp.net Identity は、多くのオンライン チュートリアルで見られるように、標準的な方法で実装されています。

IdentityModels の ApplicationUser クラスは、整数の OrganizationId などのカスタム プロパティを含むように拡張されました。これは、データベースの関係を目的として、多数のユーザーを作成し、共通の組織に割り当てることができるという考え方です。

public class ApplicationUser : IdentityUser
    {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }

        //Extended Properties
        public DateTime? BirthDate { get; set; }
        public long? OrganizationId { get; set; }

        //Key Mappings
        [ForeignKey("OrganizationId")]
        public virtual Organization Organization { get; set; }
    }

コントローラー内から現在ログインしているユーザーの OrganizationId プロパティを取得するにはどうすればよいですか? これは、ユーザーがログインするとメソッド経由で利用できるようになりますか? それとも、コントローラー メソッドが実行されるたびに、UserId に基づいてデータベースから OrganizationId を常に取得する必要がありますか?

ウェブで調べてみると、ログインした UserId などを取得するには以下を使用する必要があることがわかりました。

using Microsoft.AspNet.Identity;
...
User.Identity.GetUserId();

ただし、OrganizationId は User.Identity で使用できるプロパティではありません。OrganizationId プロパティを含めるには User.Identity を拡張する必要がありますか? そうであれば、どうすればよいでしょうか。

OrganizationId が頻繁に必要な理由は、多くのテーブル クエリが、ログインしたユーザーに関連付けられている組織に関連するデータを取得するために OrganizationId に依存しているためです。

ベストアンサー1

上記の質問のように、User.Identity のプロパティを追加のプロパティで拡張する場合は、まず次のようにしてこれらのプロパティを ApplicationUser クラスに追加します。

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }

    // Your Extended Properties
    public long? OrganizationId { get; set; }
}

次に必要なのは、次のような拡張メソッドを作成することです (私は新しい Extensions フォルダーに作成しました)。

namespace App.Extensions
{
    public static class IdentityExtensions
    {
        public static string GetOrganizationId(this IIdentity identity)
        {
            var claim = ((ClaimsIdentity)identity).FindFirst("OrganizationId");
            // Test for null to avoid issues during local testing
            return (claim != null) ? claim.Value : string.Empty;
        }
    }
}

ApplicationUser クラスで Identity を作成するときは、次のように Claim -> OrganizationId を追加するだけです。

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here => this.OrganizationId is a value stored in database against the user
        userIdentity.AddClaim(new Claim("OrganizationId", this.OrganizationId.ToString()));

        return userIdentity;
    }

クレームを追加し、拡張メソッドを配置したら、それをUser.Identityのプロパティとして利用できるようにします。アクセスしたいページ/ファイルにusingステートメントを追加します:

私の場合は、using App.Extensions;コントローラー内と@using. App.Extensions.cshtml ビュー ファイル内です。

編集:

すべてのビューに using ステートメントを追加しないようにするには、Views フォルダーに移動し、そこにある Web.config ファイルを見つけます。次に、タグを探して<namespaces>、次のように拡張機能の名前空間を追加します。

<add namespace="App.Extensions" />

ファイルを保存すれば完了です。これですべてのビューが拡張子を認識するようになります。

拡張メソッドにアクセスできます:

var orgId = User.Identity.GetOrganizationId();

おすすめ記事