2

ユーザーが複数の役割を持つ複雑な Web サイトを開発しています。ユーザーは、DB 内の他の項目にも関連付けられており、ユーザーの役割とともに、Web サイトで何を表示および実行できるかを定義します。

現在、一部のユーザーは複数の役割を持っていますが、Web サイトは複雑な構造のため、一度に 1 つの役割しか処理できません。

ユーザーがログインすると、Web サイトの隅にドロップダウンが表示され、そこで役割の 1 つを選択できるようになります。ロールが 1 つしかない場合、ドロップダウンはありません。

ここで、最後に選択したロールの値を、ユーザーのその他の設定と共に DB に保存します。彼が戻ってきたとき、このように役割はまだ記憶されています。

ドロップダウンの値は、Web サイト全体からアクセスできる必要があります。私は2つのことをしたい:

  1. 現在のロールを に保存しSessionます。
  2. メソッドをオーバーライドするか、元のメソッドのようにすべてのロールではなく、現在選択されているロールへのすべてのアクセスをチェックIsInRoleするメソッドを作成します。IsCurrentlyInRoleIsInRole

セッションの保存部分については、それを行うのが良いと思いましたGlobal.asax

    protected void Application_AuthenticateRequest(Object sender, EventArgs e) {
        if (User != null && User.Identity.IsAuthenticated) {
            //check for roles session.
            if (Session["CurrentRole"] == null) {
                NASDataContext _db = new NASDataContext();
                var userparams = _db.aspnet_Users.First(q => q.LoweredUserName == User.Identity.Name).UserParam;
                if (userparams.US_HuidigeRol.HasValue) {
                    var role = userparams.aspnet_Role;
                    if (User.IsInRole(role.LoweredRoleName)) {
                        //safe
                        Session["CurrentRole"] = role.LoweredRoleName;
                    } else {
                        userparams.US_HuidigeRol = null;
                        _db.SubmitChanges();
                    }
                } else {
                    //no value
                    //check amount of roles
                    string[] roles = Roles.GetRolesForUser(userparams.aspnet_User.UserName);
                    if (roles.Length > 0) {
                        var role = _db.aspnet_Roles.First(q => q.LoweredRoleName == roles[0].ToLower());
                        userparams.US_HuidigeRol = role.RoleId;
                        Session["CurrentRole"] = role.LoweredRoleName;
                    }
                }
            }

        }
    }

しかし、どうやらこれにより実行時エラーが発生します。Session state is not available in this context.

  1. これを修正するにはどうすればよいですか? また、このコードを配置するのに本当に最適な場所ですか?
  2. 他のすべての機能を失うことなく、ユーザー ( IPrincipal?)を拡張するにはどうすればよいですか?IsCurrentlyInRole
  3. 多分私はこれをすべて間違ってやっています.これを行うためのより良い方法はありますか?

どんな助けでも大歓迎です。

4

2 に答える 2

3

はい、Application_AuthenticateRequest でセッションにアクセスできません。
独自の CustomPrincipal を作成しました。私が最近行ったことの例を示します。

public class CustomPrincipal: IPrincipal
{
    public CustomPrincipal(IIdentity identity, string[] roles, string ActiveRole)
    {
        this.Identity = identity;
        this.Roles = roles;
        this.Code = code;
    }

    public IIdentity Identity
    {
        get;
        private set;
    }

    public string ActiveRole
    {
        get;
        private set;
    }

    public string[] Roles
    {
        get;
        private set;
    }

    public string ExtendedName { get; set; }

    // you can add your IsCurrentlyInRole 

    public bool IsInRole(string role)
    {
        return (Array.BinarySearch(this.Roles, role) >= 0 ? true : false);  
    }
}

認証チケットがある場合 (ユーザーがログインしている場合)、私の Application_AuthenticateRequest は Cookie を読み取ります。

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[My.Application.FORMS_COOKIE_NAME];
    if ((authCookie != null) && (authCookie.Value != null))
    {
        Context.User = Cookie.GetPrincipal(authCookie);
    }
}


public class Cookie
    {
    public static IPrincipal GetPrincipal(HttpCookie authCookie)
    {
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        if (authTicket != null)
        {
            string ActiveRole = "";
            string[] Roles = { "" };
            if ((authTicket.UserData != null) && (!String.IsNullOrEmpty(authTicket.UserData)))
            {
            // you have to parse the string and get the ActiveRole and Roles.
            ActiveRole = authTicket.UserData.ToString();
            Roles = authTicket.UserData.ToString();
            }
            var identity = new GenericIdentity(authTicket.Name, "FormAuthentication");
            var principal = new CustomPrincipal(identity, Roles, ActiveRole );
            principal.ExtendedName = ExtendedName;
            return (principal);
        }
        return (null);
    }
 }

認証チケットの UserData を追加して、Cookie を拡張しました。ここに追加情報を入れました:

これは、ロギング後に Cookie を作成する関数です。

    public static bool Create(string Username, bool Persistent, HttpContext currentContext, string ActiveRole , string[] Groups)
    {
        string userData = "";

        // You can store your infos
        userData = ActiveRole + "#" string.Join("|", Groups);

        FormsAuthenticationTicket authTicket =
            new FormsAuthenticationTicket(
            1,                                                                // version
            Username,
            DateTime.Now,                                                     // creation
            DateTime.Now.AddMinutes(My.Application.COOKIE_PERSISTENCE),       // Expiration 
            Persistent,                                                       // Persistent
            userData);                                                        // Additional informations

        string encryptedTicket = System.Web.Security.FormsAuthentication.Encrypt(authTicket);

        HttpCookie authCookie = new HttpCookie(My.Application.FORMS_COOKIE_NAME, encryptedTicket);

        if (Persistent)
        {
            authCookie.Expires = authTicket.Expiration;
            authCookie.Path = FormsAuthentication.FormsCookiePath;
        }

        currentContext.Response.Cookies.Add(authCookie);

        return (true);
    }

アプリのどこからでも情報にアクセスできるようになりました。

CustomPrincipal currentPrincipal = (CustomPrincipal)HttpContext.User;

カスタム プリンシパル メンバーにアクセスできるようにします: currentPrincipal.ActiveRole

ユーザーが役割 (アクティブな役割) を変更すると、Cookie を書き換えることができます。

言い忘れていましたが、authTicket.UserData に JSON でシリアル化されたクラスを格納しているため、シリアル化解除と解析が簡単です。

詳細はこちら

于 2011-02-18T13:02:32.983 に答える
0

本当にユーザーに一度に1つのアクティブな役割のみを持たせたい場合(IsInRoleをオーバーライドすることによって暗示されるように)、ユーザーの「潜在的な」役割をすべて別の場所に保存するのが最も簡単かもしれませんが、実際にはそれらのみを許可します一度に1つのASP.NET認証ロールになります。新しい役割を選択するときは、組み込みのメソッドを使用して現在の役割から削除し、新しい役割に追加します。

于 2011-02-17T15:12:23.503 に答える