这是登录功能(在验证用户名和密码后,我将用户数据加载到“user”变量并调用Login功能:
public static void Login(IUser user)
{
HttpResponse Response = HttpContext.Current.Response;
HttpRequest Request = HttpContext.Current.Request;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
user.UserId.ToString(), DateTime.Now, DateTime.Now.AddHours(12), false,
UserResolver.Serialize(user));
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(ticket));
cookie.Path = FormsAuthentication.FormsCookiePath;
Response.Cookies.Add(cookie);
string redirectUrl = user.HomePage;
Response.Redirect(redirectUrl, true);
}
UserResolver是以下类:
public class UserResolver
{
public static IUser Current
{
get
{
IUser user = null;
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
user = Desrialize(ticket.UserData);
}
return user;
}
}
public static string Serialize(IUser user)
{
StringBuilder data = new StringBuilder();
StringWriter w = new StringWriter(data);
string type = user.GetType().ToString();
//w.Write(type.Length);
w.WriteLine(user.GetType().ToString());
StringBuilder userData = new StringBuilder();
XmlSerializer serializer = new XmlSerializer(user.GetType());
serializer.Serialize(new StringWriter(userData), user);
w.Write(userData.ToString());
w.Close();
return data.ToString();
}
public static IUser Desrialize(string data)
{
StringReader r = new StringReader(data);
string typeStr = r.ReadLine();
Type type=Type.GetType(typeStr);
string userData = r.ReadToEnd();
XmlSerializer serializer = new XmlSerializer(type);
return (IUser)serializer.Deserialize(new StringReader(userData));
}
}
global.asax实现以下内容:
void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
IPrincipal p = HttpContext.Current.User;
if (p.Identity.IsAuthenticated)
{
IUser user = UserResolver.Current;
Role[] roles = user.GetUserRoles();
HttpContext.Current.User = Thread.CurrentPrincipal =
new GenericPrincipal(p.Identity, Role.ToString(roles));
}
}
第一个问题: 我做得对吗?
第二个问题 - 奇怪的是! 我传递给Login的用户变量有4个成员:UserName,Password,Name,Id。 当UserResolver.Current执行时,我得到了用户实例。 我决定更改用户结构 - 我添加了一个Warehouse对象数组。 从那时起,当UserResolver.Current执行时(登录后),HttpContext.Current.User.Identity.IsAuthenticated为false,我无法获取用户数据。 当我从用户结构中删除Warehouse []时,它再次开始正常,登录后HttpContext.Current.User.Identity.IsAuthenticated变为true。
这种奇怪行为的原因是什么?
答案 0 :(得分:3)
首先,您不需要从Global.asax执行HttpContext.Current
。 Global.asax派生自HttpApplication
。所以你需要做的就是获得Context
属性。这可能有助于使代码更清晰。
//this is all you need in your global.asax
void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if(Context.User.Identity.IsAuthenticated)
{
var user = UserResolver.Current;
Context.User = Thread.CurrentPrincipal = new UserWrapperPrincipal(user, Context.User.Identity);
}
}
//this helper class separates the complexity
public class UserWrapperPrincipal: IPrincipal, IUser
{
private readonly IUser _user;
private readonly IIdentity _identity;
public UserWrapperPrincipal(IUser user, IIdentity identity)
{
_user = user;
_identity = identity;
}
private IList<string> RoleNames
{
get { return _user.GetUserRoles().Select(role => role.ToString()); }
}
public IIdentity Identity { get { return _identity; } }
public bool IsInRole(string role) { return RoleNames.Contains(role); }
}
根据您的错误,似乎问题是您的序列化功能或反序列化功能会破坏数据。但是,问题区域可能不是那些功能。序列化Warehouse对象(序列化复杂类型有时可能很棘手)或实际数组的序列化都存在问题。由于您使用的是默认的.NET XmlSerializer
,因此有一篇很好的文章介绍了如何在http://www.diranieh.com/NETSerialization/XMLSerialization.htm自定义和控制处理不同对象的方式。
另外请注意,您确定这是将这些数据存储在应用程序中的最佳方式吗?存储用户ID和名称是有道理的。当您开始在cookie中存储复杂对象的序列化数组时,它可能表示您没有正确地解决问题。
答案 1 :(得分:1)
我猜你的代码是在某个地方的登录事件中,并且你构建了一个自定义表单身份验证。
您还需要在每个页面请求上从cookie构建User对象
public class AuthHttpModule : IHttpModule {
public virtual void Init(HttpApplication app) {
app.AuthenticateRequest += new EventHandler(app_AuthenticateRequest);
}
private void app_AuthenticateRequest(object source, EventArgs e) {
HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null) {
HttpContext.Current.User = null;
} else {
cookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(ticket), new string[0]);
}
bool result = HttpContext.Current.Request.IsAuthenticated;
}
}
修改强>
尝试将此添加到您的全局
void Application_AuthenticateRequest(Object sender, EventArgs e)
HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null) {
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(ticket), new string[0]);
}
}