web-dev-qa-db-ja.com

フォーム認証を使用して、ログに記録されたユーザー情報をASP.NET MVCのどこに保存しますか?

アプリケーションでASP.NETMVCとフォーム認証を使用しています。基本的に、私はFormsAuthentication.SetAuthCookieを使用してログインし、FormsAuthentication.SignOutを使用してログアウトします。

HttpContext.Current.User.Identityにユーザー名を保存しましたが、ログに記録されたユーザーに関する詳細情報が必要です。 User obj全体をセッションに保存したくないのは、それが大きく、必要以上の情報が含まれている可能性があるためです。

必要な属性のみを使用してLoggedUserInfoというクラスを作成し、それをセッションvariableに追加するのは良い考えだと思いますか?これは良いアプローチですか?

それとももっと良いアイデアがありますか?

22

私はこのソリューションを使用します:

ASP.NET 2.0フォーム認証-カスタマイズされたシンプルな状態を維持

要約すると、私は独自のIPrincipal実装を作成しました。 HttpContext.Current.Cacheに保存されます。なんらかの理由で紛失した場合は、クライアント側の認証Cookieからのユーザー名を取得し、再構築できます。このソリューションは、簡単に失われる可能性のあるセッションに依存していません。

[〜#〜]編集[〜#〜]

コントローラでプリンシパルを使用してテスト可能にする場合は、次のようにします。

    private MyPrincipal _myPrincipal;
    MyPrincipal MyPrincipal
    {
        get
        {
            if (_myPrincipal == null)
                return (MyPrincipal)User;
            return _myPrincipal;
        }
        set
        {
            _myPrincipal = value;
        }
    }

テストでは、テスト用に準備されたオブジェクトを設定します。それ以外の場合は、HttpContextから取得されます。そして今、私は考え始めました、なぜ私はそれをするためにNinjectを使うのですか?

8
LukLed

私は実際に、次のようなログオンアクションメソッドで設定したCustomPrincipalとCustomIdentityを使用するのが好きです。

        if (!String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password) && _authService.IsValidLogin(username, password))
        {
            User objUser = _userService.GetUserByName(username);
            if (objUser != null)
            {
                //** Construct the userdata string
                string userData = objUser.RoleName + "|" + objUser.DistrictID + "|" + objUser.DistrictName + "|" + objUser.ID + "|" + objUser.DisplayName;
                HttpCookie authCookie = FormsAuthentication.GetAuthCookie(username, rememberMe.GetValueOrDefault());
                FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
                FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, userData);
                authCookie.Value = FormsAuthentication.Encrypt(newTicket);
                Response.Cookies.Add(authCookie);
                return RedirectToAction("Index", "Absence");
            }
            else
            {
                return RedirectToAction("LogOn", "Account");
            }
        }
        else
        {
            return RedirectToAction("LogOn", "Account");
        }

次に、カスタムプリンシパルで、コンストラクターに渡した特定の情報にアクセスするメソッドを作成できます。

((CustomIdentity)((CustomPrincipal)HttpContext.Current.User).Identity).DisplayName;

ここで、DisplayNameプロパティはCustomIdentityクラスで宣言されています。

4
user205258

サーバー側でセッションに保存します。

例えば。

// Make this as light as possible and store only what you need
public class UserCedentials
{
    public string Username { get; set; }
    public string SomeOtherInfo { get; set; }
    // etc...
}

次に、サインインしたら、次の手順を実行してユーザー情報を保存します。

// Should make typesafe accessors for your session objects but you will
// get the point from this example
Session["UserCredentials"] = new UserCredentials()
    { Username = "SomeUserName", SomeOtherInfo = "SomeMoreData" };

次に、必要なときにいつでもフェッチします。

UserCredentials user = (UserCredentials)(Session["UserCredentials"]);

MVCでカスタム承認を行うことに関するいくつかの質問/回答を書きました: セッションデータに基づいてASP.NET MVCで承認チェックを実装する方法は?

Authorizeタグはどのように機能しますか?-Asp.net Mvc

3
Kelsey

さて、あなたはこれらをどこかに保管しなければならないでしょう。ただし、2つの主な可能性のある場所:

サーバー

それらをSessionに入れることができます。メモリの浪費を避けるために実際に必要なデータのみを保持する別のクラスを作成することをお勧めします。または、大量の同時ユーザーがいる場合に多くのDB呼び出しが発生する可能性があるキャッシュに保存することもできます。

クライアント

この場合、別のクラスでデータの量を制限できる場合は、それに制限し、任意の方法を使用してデータをシリアル化し、クライアントに送信します。 CookieまたはURIのいずれか(長さが許可され、Cookieが無効になっている場合)...

これらの考えの結果:
ここでの主なことは、この方法で多くのメモリリソースを獲得した場合に、別のクラスを作成することです。だから、それはあなたが最初にすべきことです。

2
Robert Koritnik