在 MVC 中实现自定义身份和 IPrincipal
Posted
技术标签:
【中文标题】在 MVC 中实现自定义身份和 IPrincipal【英文标题】:Implementing a Custom Identity and IPrincipal in MVC 【发布时间】:2010-12-25 10:29:21 【问题描述】:我有一个基本的 MVC 2 beta 应用程序,我正在尝试实现自定义身份和主体类。
我创建了实现 IIdentity 和 IPrincipal 接口的类,将它们实例化,然后在 Global.asax 的 Application_AuthenticateRequest 中将 CustomPrincipal 对象分配给我的 Context.User。
这一切都成功了,对象看起来不错。当我开始呈现视图时,页面现在失败了。第一个失败是在以下代码行的默认 LogoOnUserControl 视图中:
[ <%= html.ActionLink("Log Off", "LogOff", "Account") %> ]
如果我把它拉出来,那么它会在不同的“Html.ActionLink”代码行上失败。
我收到的错误是:
类型异常 'System.Runtime.Serialization.SerializationException' 发生在 WebDev.WebHost40.dll 但 未在用户代码中处理
附加信息:类型不是 为会员解决 '模型.实体.用户身份,模型, 版本=1.0.0.0,文化=中性, PublicKeyToken=null'。
为了在 MVC 中使用自定义身份,我需要在身份中实现一些其他属性吗?我尝试在 Identity 类中实现 [Serializable()] 但似乎没有影响。
更新: 我已经尝试了 3-4 种替代方法来实现这一点,但仍然失败并出现同样的错误。如果我直接使用 GenericIdentity/GenericPrincipal 类,它不会出错。
GenericIdentity ident = new GenericIdentity("jzxcvcx");
GenericPrincipal princ = new GenericPrincipal(ident, null);
Context.User = princ;
但这让我无处可去,因为我试图使用 CustomIdentity 来保存几个属性。如果我为我的 CustomIdentity/CustomPrincipal 实现 IIdentity/IPrincipal 接口或继承 GenericIdentity/GenericPrincipal,则会失败并出现上述原始错误。
【问题讨论】:
回复:赞成票...您是否也看到类似的问题? 【参考方案1】:在网络的帮助下,我想出了这一点 :) 诀窍是您必须在实现 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"
【讨论】:
这个功能是废话......它自 2006 年以来就已经存在,并且仍然影响着我的 asp.net mvc-3 应用程序。 这解决了我的问题。 IPrincipal 也是如此。 为什么在反序列化代码中创建一个新的GenericIdentity
而不是CustomIdentity
? => `GenericIdentity gIdent = new GenericIdentity(...)' ??
只是想注意System.ISerializable
和System.Runtime.Serialization.ISerializable
之间的区别。在意识到第二个 (System.Runtime.Serialization.ISerializable) 是我需要的之前,我与第一个斗争了一段时间。【参考方案2】:
我遇到了同样的问题。我通过将创建的主体从 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;
【讨论】:
【参考方案3】:当我从 MarshalByRefObject
继承我的 Identity 类时,它似乎可以工作。
另请注意:使用 Linq-to-Sql 时没有问题。我切换到 Entity-Framework 并砰的一声,我收到了上面的消息。
【讨论】:
***.com/questions/6503380/… 还有更多关于 marshalbyrefobject 的内容以上是关于在 MVC 中实现自定义身份和 IPrincipal的主要内容,如果未能解决你的问题,请参考以下文章
我们如何在 Laravel 中实现自定义的仅 API 身份验证
在 ASP.NET 5 (vNext) MVC 6 中实现自定义路由器