0

数日間FormsAuthenticationを調査した後、シリアル化されたオブジェクトをFormsAuth cookieのUserDataプロパティに格納し、HttpContext.Current.UserにカスタムIPrincipalオブジェクトを使用することにしました。

私が見つけたガイドのほとんどは、IPrincipalオブジェクトをオブジェクトにキャストすると言っています。ただし、毎回無効なキャスト例外が発生します。私は何が間違っているのですか?

MyUserData

public class MyUserData
{
    public long UserId { get; set; }
    public string Username { get; set; }
    public bool IsSuperUser { get; set; }
    public string UnitCode { get; set; }
    public string EmailAddress { get; set; }
    public List<string> Roles { get; set; }

    // Serialize    
    public override string ToString()
    {
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        string result = serializer.Serialize(this);
        return result;
    }

    // Deserialize
    public static MyUserData FromString(string text)
    {
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        return serializer.Deserialize<MyUserData>(text);
    }
}

CustomPlatformPrincipal

public class MyCustomPrincipal : IPrincipal
{
    public MyUserData MyUserData { get; set; }
    public IIdentity Identity { get; private set; }

    public MyCustomPrincipal(MyUserData myUserData)
    {
        MyUserData = myUserData;
        Identity = new GenericIdentity(myUserData.Username);
    }

    public bool IsInRole(string role)
    {
        return MyUserData.Roles.Contains(role);
    }
}

Global.asax.cs

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    {
        HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie == null || authCookie.Value == "")
        {
            return;
        }

        FormsAuthenticationTicket authTicket;
        try
        {
            authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        }
        catch
        {
            return;
        }

        if (Context.User != null)
        {
            // the from string deserializes the data
            MyUserData myUserData = MyUserData.FromString(authTicket.UserData);
            Context.User = new MyCustomPrincipal(myUserData);
        }
    }

マイページ

var myUserData = ((MyCustomPrincipal)(HttpContext.Current.User)).MyUserData;
// invalid cast exception (can't cast IPrincipal to MyCustomPrincipal)

私がフォローしていた記事:http://primaryobjects.com/CMS/Article147.aspx

したがって、データを取得できる唯一の方法は、認証Cookieを復号化してから、authCookieのuserData文字列を逆シリアル化することです。

助言がありますか?

アップデート

このSOの質問に関する提案に従ってみました:MVCでのカスタムIDとIPrincipalの実装

以下のコードですが、機能しませんでした。

[Serializable]
public class MyCustomPrincipal : IPrincipal, ISerializable
{
    public CustomUserData CustomUserData { get; set; }
    public IIdentity Identity { get; private set; }

    //public MyCustomPrincipal (IIdentity identity) { Identity = identity; }

    public MyCustomPrincipal(CustomUserData customUserData)
    {
        CustomUserData = customUserData;
        Identity = new GenericIdentity(customUserData.Username);
    }

    public bool IsInRole(string role)
    {
        return PlatformUserData.Roles.Contains(role);
    }


    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (context.State == StreamingContextStates.CrossAppDomain)
        {
            MyCustomPrincipal principal = new MyCustomPrincipal (this.CustomUserData );
            info.SetType(principal.GetType());

            System.Reflection.MemberInfo[] serializableMembers;
            object[] serializableValues;

            serializableMembers = FormatterServices.GetSerializableMembers(principal.GetType());
            serializableValues = FormatterServices.GetObjectData(principal, serializableMembers);

            for (int i = 0; i < serializableMembers.Length; i++)
            {
                info.AddValue(serializableMembers[i].Name, serializableValues[i]);
            }
        }
        else
        {
            throw new InvalidOperationException("Serialization not supported");
        }
    }
}
4

1 に答える 1

2

デバッグモードで実行しましたか?HttpContext.Current.Userにブレークポイントを設定すると、その時点でユーザーがどのタイプであったかがわかります。また、Application_AuthenticateRequestメソッドから、Userが期待されるタイプになるという保証はありません。カスタムタイプの設定に到達する前に、多くの出口点があります。このコードでさえ:Context.User!=null。それはあなたの期待に誤りでした。Context.Userの詳細については説明していませんが、コンテキストに関しては、Context.Userがカスタムユーザーであると期待していました。したがって、有効なチェックは次のようになります。

var custom = Context.Current as MyCustomPrinciple;
if(custom == null)
{
// Your construct code here.
}

私の強く提案するのは、何が起こっているのかを正確に確認するには、デバッグモードにする必要があるということです。

于 2013-01-25T02:12:43.397 に答える