• 深入分析自定义表单验证与Cookies


    深入分析自定义表单验证与Cookies
    [Key words:Form,Security, FormsAuthentication, FormsAuthenticationTicket,cookies]

    在ASP.net项目中,身份验证为我们提供了很多方便,而做为中小型的项目,一般都采用了表单验证。关于ASP.net里的表单验证,可以MSDN里的相关文章里找到很详细的说明。而且单单只是表单认证也是很简单的,这里就不去讨论它了。这里我想主要分析一下自己定义认证票据及Cookies之间的关系。
    先给一个自己定义票据的例子:

            public virtual  void Login(bool i_autoLogin)
            
    {
                
    string m_userData    = this.m_userID.ToString()+","+this.m_loginName+","+this.m_userType.ToString();
                FormsAuthenticationTicket ticket 
    = new FormsAuthenticationTicket(
                    
    1,
                    
    "WebbUser",
                    System.DateTime.Now,
                    System.DateTime.Now.AddDays(
    30),
                    i_autoLogin,
                    m_userData,
                    
    "");
                
    string encTicket = FormsAuthentication.Encrypt(ticket);
                HttpContext.Current.Response.Cookies.Set(
    new HttpCookie("WebbUser", encTicket));
            }

    其中的m_userData可是自己定义的任何字符串,最后通过FormsAuthentication.Encrypt(ticket)加密然后添加到客户端。关于FormsAuthenticationTicket,在MSDN里也有相关说明。而我想说的是它的最后一个参数:MSDN里明确表示,要用"/",而通过多次测试,发现用其它任何有意义的字符串都可以,但不管你加了什么字符后,你所建立的表单票据都成了临时的了(多次测试,几乎让我疯掉了),而这里的时间参数根本无效即cookies建立在浏览器内存里,关闭浏览器后就无效,也就根本起为不了自动登录的功能。反到是把最后一个参数设定为空字符串,可以建立永久的Cookies。这里,我用了空串,让它建立永久的Cookies。

    而最后我也用了Set Cookies而不是Add,这是有道理的。就算是第一次建立Cookies也可以建立成功,而用Add则会添加新的Cookies.其实我也不大明白这两者的区别。
    取回自己定义的票据数据:当然,最后还要把取回来的数据设定成可用的格式。

            protected void GetDataFromCookie()
            
    {
                
    if(User.Identity.IsAuthenticated)
                
    {
                    
    string m_userData;
                    FormsIdentity id 
    = (FormsIdentity)User.Identity;
                    FormsAuthenticationTicket ticket 
    = id.Ticket;
                    m_userData        
    = ticket.UserData;
                    
    if(m_userData!=null)
                    
    {
                        SetUserData(m_userData);
                    }

                }

            }


    看上去这些很完美了,然而让我发疯的是它的注销。因为这里自己定义了票据,而这里的票据又是以Cookies添加在客户端的,所以用简单的:FormsAuthentication.SignOut();根本无效。于是简单的方法是想到自己处理Cookies,而处理Cookies就让我郁闷了。先看看Trace的结果:

    Cookies Collection

    Name Value Size
    WebbUser 28B93F4A0C8791830157006500620062005500730065007200000042C9ABA1550CC601014249109AE823C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    ASP.NET_SessionId fvfyp4b2fchyvwy1pwowt5ur 42
    WebbUser 28B93F4A0C8791830157006500620062005500730065007200000042C9ABA1550CC601014249109AE823C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    14
    我百思不得其解的是:为什么会有两个WebbUser?而且值完全一样?
    做一个小的测试:

            private void Button1_Click(object sender, System.EventArgs e)
            
    {
                HttpCookie m_cookie 
    = Request.Cookies["WebbUser"];
                m_cookie.Value        
    = "Changed";
                Response.Cookies.Set(m_cookie);
            }

    其后我得到的结果是:

    Cookies Collection

    Name Value Size
    WebbUser 28B93F4A0C8791830157006500620062005500730065007200000042C9ABA1550CC601014249109AE823C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    ASP.NET_SessionId h1rdcxu21s4awxmupsiw5znc 42
    WebbUser Changed 16
    这里明显的只改变了一个Cookies,而且说明这里确实有两个Cookies在“系统”里(谁知道在哪里呀)。而这里改变了其实的一个。关闭浏览器,再直接打开,然后得到:

    Cookies Collection

    Name Value Size
    WebbUser Changed 16
    ASP.NET_SessionId 55icvo452ltsid454jtuklf0 42

    猜测以下结论:
    1、一个Cookie是在浏览器里,而另一个则是在Cookie文件里。
    2、修改时,只修改了文件里的那一个,而浏览器里的没有变。但表单验证以文件为准,所以当我自己修改Cookies后,表单验证是失效了的。

    再次登录,得到以下内容:

    Cookies Collection

    Name Value Size
    WebbUser Changed 16
    ASP.NET_SessionId 4koyqb45dqm1qm551eahe245 42
    WebbUser 00E5C94AF9B385BA0157006500620062005500730065007200000064B91EC4E40CC60101643983BC7724C601320031002C00570075002E0043006F0075006E007400720079002C0043006C00690065006E00740000000000 185

    这说明登录是失败的,因为根据上面的猜测,它只是在浏览器里建立一个临时的认证,而ASP.net要以文件认证,所以登录后,又被导入到登录页面。这让我很郁闷,因为我我的登录确实是重新设置了Cookies的。下面的测试更让人郁闷:

            private void Button4_Click(object sender, System.EventArgs e)
            
    {
                HttpCookieCollection m_cookies    
    = Request.Cookies;
                
    for(int i=0;i<m_cookies.Count;i++)
                
    {
                    m_cookies[i].Value        
    = DateTime.Now.ToString();
                    m_cookies[i].Expires    
    = DateTime.Now.AddMinutes(-1);
                    Response.Cookies.Set(m_cookies[i]);
                }

            }

    结果是:

    Cookies Collection

    Name Value Size
    WebbUser Changed 16
    ASP.NET_SessionId 4koyqb45dqm1qm551eahe245 42
    WebbUser 00E5C94AF9B385BA0157006500620062005500730065007200000064B91EC4E40CC60101643983BC7724C601320031002C00570075002E0043006F0075006E007400720079002C0043006C00690065006E00740000000000 185
    WebbUser 12/30/2005 10:06:14 AM 31
    ASP.NET_SessionId 12/30/2005 10:06:14 AM 40
    显然,我修改了两个Cookies,根据ASP.NET_SessionId是在浏览器里的依据,可以猜测,所做的修改都只在浏览器里。而这里仍然保留了另一个正确的Cookie在浏览器里,也就是说,上面的Set方法完全无效,而只是添加了临时的Cookies.不解。。。。。。而接下来的问题是,我修改了论证后的Cookies,如何再次可以登录系统呢(当然,用IE选项删除所有Cookies是一最终解决方法)?
    修改登录代码:

            public virtual  void Login(bool i_autoLogin)
            
    {
                
    string m_userData    = this.m_userID.ToString()+","+this.m_loginName+","+this.m_userType.ToString();
                FormsAuthenticationTicket ticket 
    = new FormsAuthenticationTicket(
                    
    1,
                    
    "WebbUser",
                    System.DateTime.Now,
                    System.DateTime.Now.AddDays(
    30),
                    i_autoLogin,
                    m_userData,
                    
    "");
                
    string encTicket = FormsAuthentication.Encrypt(ticket);
                HttpCookie m_cookie    
    = HttpContext.Current.Request.Cookies.Get("WebbUser");
                WaveHelper.TraceMsg(m_cookie.Value);
                m_cookie.Value        
    = encTicket;
                
    //HttpContext.Current.Response.Cookies.Set(new HttpCookie("WebbUser", encTicket));
                HttpContext.Current.Response.Cookies.Set(m_cookie);
            }

    测试输出:12/30/2005 10:14:32 AM Changed
    说明取得了文件Cooikes里的正确值,但设置却只是临时,这是什么道理呢?为什么第一次登录的时候可以呢?而且第一次修改为"Changed"的时候如此的理所当然,以致于可以想到可以把它设定为任何想要的内容,可惜其后的所有设定都失败。
    更为有意思的事,登录后,刷新页面可以得到页面里不断的添加新的Cooikes,而最多只有三个。不断刷新页面,得到下面的结果:

    1
    Cookies Collection

    Name Value Size
    WebbUser E7CCE30B0614E23101570065006200620055007300650072000000BC1DF89AEB0CC60101BC9D5C937E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    ASP.NET_SessionId 1ck3eunw3fkiiuulbxvvrg45 42
    WebbUser CFCF23BA7B3631F801570065006200620055007300650072000000584EDA96EB0CC6010158CE3E8F7E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    WebbUser D0E2E460A26850DC015700650062006200550073006500720000005625A99DEB0CC6010156A50D967E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    2

    Cookies Collection

    Name Value Size
    WebbUser D0E2E460A26850DC015700650062006200550073006500720000005625A99DEB0CC6010156A50D967E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    ASP.NET_SessionId 1ck3eunw3fkiiuulbxvvrg45 42
    WebbUser CFCF23BA7B3631F801570065006200620055007300650072000000584EDA96EB0CC6010158CE3E8F7E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    WebbUser 525BE5D26ED817F0015700650062006200550073006500720000001C9BB3ACEB0CC601011C1B18A57E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173

    3
    Cookies Collection

    Name Value Size
    WebbUser 525BE5D26ED817F0015700650062006200550073006500720000001C9BB3ACEB0CC601011C1B18A57E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    ASP.NET_SessionId 1ck3eunw3fkiiuulbxvvrg45 42
    WebbUser CFCF23BA7B3631F801570065006200620055007300650072000000584EDA96EB0CC6010158CE3E8F7E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    WebbUser C13C21C845D22DDE015700650062006200550073006500720000001CA9DAB3EB0CC601011C293FAC7E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    4

    Cookies Collection

    Name Value Size
    WebbUser C13C21C845D22DDE015700650062006200550073006500720000001CA9DAB3EB0CC601011C293FAC7E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    ASP.NET_SessionId 1ck3eunw3fkiiuulbxvvrg45 42
    WebbUser CFCF23BA7B3631F801570065006200620055007300650072000000584EDA96EB0CC6010158CE3E8F7E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    WebbUser 1E7280709500E99E015700650062006200550073006500720000006A377CC2EB0CC601016AB7E0BA7E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    显然,每次登录后得到的认证加密数据是不一样的,但我们可以看到第二个WebbUser一直没有变!为什么?而其它两个则是不断的由新的替换旧的。

    我已经没有办法区分它们的关系了,还想去猜测一下,哪几个在内存里,哪一个或者哪几个在文件里?关闭浏览器,再打开,得到下面的结果?两个?昏。。。。。

    Cookies Collection

    Name Value Size
    WebbUser 1E7280709500E99E015700650062006200550073006500720000006A377CC2EB0CC601016AB7E0BA7E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    WebbUser 1E7280709500E99E015700650062006200550073006500720000006A377CC2EB0CC601016AB7E0BA7E24C60131002C007700650062006200610064006D0069006E002C00410064006D0069006E0000000000 173
    ASP.NET_SessionId 1nt5n0uwvcavxfev3xgolh55 42

    14

    修改后刷新,得到下面的结果:

    Cookies Collection

    Name Value Size
    WebbUser 12/30/2005 10:55:57 AM 31
    ASP.NET_SessionId fgc1pb45r3y4qx55a2dke2y3 42
    WebbUser 12/30/2005 10:56:06 AM 31
    WebbUser 12/30/2005 10:56:13 AM 31

    几乎疯掉了,如果不能修改它的值,为什么可以在第一次修改,而其后所有的修改都失败,包括过期时间的修改。没道理。。。。。。。。。。而它对认证还起作用,也是没道理的。。。。。

    我只能给出以下结论与解决方法了:1、这是ASP.net及浏览器间存在的问题。2、放弃使用自定义票据的表单验证。因为我并不想让所有出了问题的用户都去删除Cookies.

    最后通过几次测试发现,可以用Add方法覆盖式的修改Cookies,但不管怎样,这里的Cookies与自己定义的表单验证是有问题的。最后为了安全起见,在项目里又添加了一个一般Cookies做为后备,这样在验证退出或者验证失败的时候,还可以用一般的Cookies再验证一次,然后强行退出要求用户登录。当然,如果登录不成功的话,那就只有手动删除Cookies了。伤心呀。。。。。。。。。。

    ================================
      /\_/\                        
     (=^o^=)  Wu.Country@侠缘      
     (~)@(~)  一辈子,用心做一件事!
    --------------------------------
      学而不思则罔,思而不学则怠!  
    ================================
  • 相关阅读:
    迁移式学习
    VMware Workstation 16激活码
    OpenStack安装部署
    git码云操作
    vs 2019 正则替换
    linux中Redis单机安装
    ASP.NET/C#执行数据库过程函数带RETURN的项目接收。
    IDEA配置部属Tomcat
    Java集合之HashMap源码分析(put()方法)
    反编译一款APP然后重新打包(Windows环境)
  • 原文地址:https://www.cnblogs.com/WuCountry/p/307577.html
Copyright © 2020-2023  润新知