在MVC中实现自定义标识和IPrincipal

时间:2009-12-10 21:06:56

标签: asp.net-mvc-2 iprincipal iidentity

我有一个基本的MVC 2 beta应用程序,我正在尝试实现自定义的Identity和Principal类。

我创建了实现IIdentity和IPrincipal接口的类,实例化它们,然后将CustomPrincipal对象分配给Global.asax的Application_AuthenticateRequest中的Context.User。

这一切都成功,对象看起来很好。当我开始渲染视图时,页面现在失败了。第一个失败是在以下代码行的默认LogoOnUserControl视图中:

 [ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> ]

如果我把它拉出来然后在另一个“Html.ActionLink”代码行上失败。

我收到的错误是:

  

类型的例外   'System.Runtime.Serialization.SerializationException'   发生在WebDev.WebHost40.dll但是   未在用户代码中处理

     

附加信息:类型不是   为会员解决   “Model.Entities.UserIdentity,型号,   版本= 1.0.0.0,文化=中立,   公钥=空”。

为了在MVC中使用自定义身份,是否需要在我的身份中实现一些其他属性?我试图在Identity类中实现[Serializable()]但它似乎没有影响。

更新 我尝试了3-4种实现此方法的替代方法但仍然失败并出现相同的错误。如果我直接使用GenericIdentity / GenericPrincipal类,则不会出错。

GenericIdentity ident = new GenericIdentity("jzxcvcx");
GenericPrincipal princ = new GenericPrincipal(ident, null);
Context.User = princ;

但是这让我无处可去,因为我试图使用CustomIdentity来保存几个属性。如果我实现了IIdentity / IPrincipal接口或继承了我的CustomIdentity / CustomPrincipal的GenericIdentity / GenericPrincipal,它将失败并显示上面的原始错误。

3 个答案:

答案 0 :(得分:16)

我在网上得到一点帮助时想出了这一点:)诀窍是你必须在你的类中实现IIdentity的ISerializable接口。我希望这有助于拯救别人一段时间:)

班级声明:

[Serializable]
    public class ForumUserIdentity : IIdentity, ISerializable

ISerializable的实施:

#region ISerializable Members

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (context.State == StreamingContextStates.CrossAppDomain)
            {
                GenericIdentity gIdent = new GenericIdentity(this.Name, this.AuthenticationType);
                info.SetType(gIdent.GetType());

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

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

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

        #endregion

以下是link to the article that has more detail on the "Feature"

答案 1 :(得分:11)

我遇到了同样的问题。我通过将我的主体创建从MvcApplication_AuthenticateRequest移动到MvcApplication_PostAuthenticateRequest来解决它。 我不知道为什么/如何,但它解决了问题:)

        void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
    {
        HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie != null)
        {
            string encTicket = authCookie.Value;
            if (!String.IsNullOrEmpty(encTicket))
            {
                FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(encTicket);
                BiamedIdentity id = new BiamedIdentity(ticket);
                GenericPrincipal prin = new GenericPrincipal(id, null);
                HttpContext.Current.User = prin;
            }
        }
    }

答案 2 :(得分:4)

对我而言,当我从MarshalByRefObject继承我的Identity类时似乎有效。

另请注意:使用Linq-to-Sql时没有问题。我切换到Entity-Framework并发出声音,我收到了上述消息。