1. ホーム
  2. asp.net-mvc

[解決済み] User.Identityの利用可能なプロパティを拡張する方法

2022-06-20 17:10:35

質問

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で利用可能なプロパティではありません。User.Identityを拡張してOrganizationIdプロパティを含める必要がありますか。もしそうなら、どのようにこれを行うか。

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

どのように解決するには?

上記の質問のように、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 View ファイルにあります。

をEDITします。

すべてのViewにusing文を追加しないようにするためにできることは、Viewsフォルダに移動し、そこにあるWeb.configファイルを見つけることです。 ここで <namespaces> タグを探し、そこに拡張用の名前空間を追加します。

<add namespace="App.Extensions" />

ファイルを保存して完了です。これで、すべてのViewがあなたの拡張機能を知ることができます。

Extension Methodにアクセスすることができます。

var orgId = User.Identity.GetOrganizationId();