IsAuthenticated 是假的!奇怪的行为复习问题

发布于 2024-10-12 09:10:02 字数 2992 浏览 8 评论 0原文

这是登录函数(在验证用户名和密码后,我将用户数据加载到“user”变量中并调用登录函数:

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。

这种奇怪行为的原因是什么?

This is the login function (after I validate user name and password, I load user data into "user" variable and call Login function:

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 is the following class:

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));
    }
}

And the global.asax implements the following:

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));
    }
}

First question:
Am I do it right?

Second question - weird thing!
The user variable I pass to Login has 4 members: UserName, Password, Name, Id.
When UserResolver.Current executed, I got the user instance.
I descided to change the user structure - I add an array of Warehouse object.
Since that time, when UserResolver.Current executed (after Login), HttpContext.Current.User.Identity.IsAuthenticated was false and I couldn't get the user data.
When I removed the Warehouse[] from user structure, it starts to be ok again and HttpContext.Current.User.Identity.IsAuthenticated become true after I Login.

What is the reason to this weird behaviour?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ヤ经典坏疍 2024-10-19 09:10:03

首先,您不需要从 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 中存储复杂对象的序列化数组时,这可能表明您一开始就没有正确解决问题。

First, you don't need to do an HttpContext.Current from Global.asax. Global.asax derives from HttpApplication. So all you need to do is to get the Context property. This might help make that code a little cleaner.

    //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); }

    }

Based on your error, it seems like the issue is that either your serializing function or your deserializing function corrupts the data. However, the problem area is probably not those functions. Either there is an issue in serializing the Warehouse object (serializing complex types can sometimes be tricky), or in the serialization of the actual array. Since you are using the default .NET XmlSerializer, There is a good article on customizing and controlling the way different objects are handled available at http://www.diranieh.com/NETSerialization/XMLSerialization.htm .

On another note, are you sure that this is the best way for you to store this data in your application? Storing a user-id and name makes sense. When you start storing serialized arrays of complex objects in your cookie, it might indicate you are not approaching the problem correctly to begin with.

萌能量女王 2024-10-19 09:10:03

我猜测您的代码位于某处的登录事件中,并且您正在构建自定义表单身份验证。

然后,您还需要在每个页面请求上从 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]);
    }
}

I am guessing that your code is in a log on event somewhere and your building a custom forms auth.

You also need to then build the User object from the cookie on every page request

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;
    }
}

EDIT

Try adding this to your global

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]);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文