深入分析自定义表单验证与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了。伤心呀。。。。。。。。。。

转载于:https://www.cnblogs.com/WuCountry/archive/2005/12/29/307577.html

深入分析自定义表单验证与Cookies相关推荐

  1. Django 表单验证之自定义表单验证器

    本文基于Django 表单验证 一文,补充完善表单验证器之自定义表单验证器 具体步骤总结如下: 第一:在formValidation.py 文件中,添加自定义名称敏感验证器(NameValidatio ...

  2. 表单验证与自定义表单验证

    / 验证规则 rules: { // 多个验证用数组 单个验证用对象// 验证账号acc: [{ required: true, message: '不能为空', trigger: 'blur' }, ...

  3. 记录element-ui自定义表单验证上传身份证正反面

    大概是这个样式 两个上传组件写在一个form-item里进行自定义表单验证 每次验证,通过判断上传组件绑定的值进行判断,callback不同的提示错误 <template><div& ...

  4. iview自定义表单验证

    @[TOC] iview自定义表单验证 之前总结过iview简单表单验证: https://blog.csdn.net/A_LL_IS_WELL/article/details/111227468ht ...

  5. vue + element 自定义表单验证的时候 需要通过请求后端接口验证

    vue + element 自定义表单验证的时候 需要通过请求后端接口验证 做vue项目的时候遇到了一个需求,在验证某个表单项时不仅需要是必填项而且要去通过接口校验是否有重复值. // templat ...

  6. antd vue表单验证_antd-for-vue 表单验证失效 自定义表单验证使表单非空验证失效(其他验证失效)...

    ## antd-for-vue 表单验证失效 自定义表单验证使表单非空验证失效(其他验证失效) ##### antd 的 表单校验方法包括 validateFields 和 validateField ...

  7. ant-design-vue 表单验证和 validator 自定义表单验证

    在 ant-design-vue 中,提供 FormModel 表单组件,且支持 v-model 数据绑定,同时可以校验和提交功能的表单. 一.表单验证 <a-form-modelref=&qu ...

  8. vux使用方法 php,如何使用vux-ui自定义表单验证

    这次给大家带来如何使用vux-ui自定义表单验证,使用vux-ui自定义表单验证的注意事项有哪些,下面就是实战案例,一起来看一下. 初学框架vue搭配vux使用发现这个UI库使用有些力不从心.下面说说 ...

  9. AngularJS自定义表单验证

    Angular实现了大部分常用的HTML5的表单控件的类型(text, number, url, email, date, radio, checkbox),也实现了很多指令做为验证(required ...

  10. ElementUI使用问题记录:设置路由+iconfont图标+自定义表单验证

    一.关于导航怎么设置路由 1.在el-menu这个标签的属性中添加 router ,官方文档的解释是:启用vue-router 这种模式 2.在el-menu-item标签中的index属性直接书写路 ...

最新文章

  1. 不能上传图片和编辑内容很慢,望改进
  2. java解析html的table
  3. Mac OS使用技巧之三:发射无线网络信号的方法
  4. 【渝粤教育】电大中专电商运营实操 (8)作业 题库
  5. 矩阵的“之”字形打印
  6. python常用文本处理功能
  7. How to make your 100k to 10k (5)
  8. JS DOM节点的增删改查
  9. Spring-MVC案例:Spitter的笔记
  10. 《网络与信息安全B》教学大纲
  11. 多元函数的牛顿迭代法
  12. 使用JAVA实现邮件发送功能
  13. JSP基础教程【1】
  14. Unity3d 联通沃商店接入问题
  15. Oracle 的SQL*LOADER中optionally enclosed的作用
  16. git clone项目文件时报错解决remote: Enumerating objects: 19, done. remote: Counting objects: 100% (19/19), don
  17. 必应每日一图直接获取及接口
  18. 智搜Giiso写作机器人调研
  19. MediaCodec 、x264、faac 实现音视频编码并通过 rtmp 协议实现推流
  20. 差分龄期(age of diff)对RTK定位精度的影响分析(包含RTKLIB实际测试)

热门文章

  1. 在电子表格计算架构上应用稀疏数组技术的设计
  2. eclipse Unable to build: the file dx.jar was not loaded from the SDK folder的解决办法
  3. linux系统vi编辑器按esc没反应,关于ubuntu14.04版本vi编辑模式按下ESC无法回到一般模式的问题...
  4. 搭建ftp_Windows 10搭建FTP服务器!
  5. java动态代理_Java核心 -- 动态代理
  6. 浏览器request得不到cookie_Servlet第五篇「介绍会话技术、Cookie的API、详解、应用」...
  7. 恋舞ol服务器维护中,《恋舞OL》更新维护公告
  8. 类的虚函数表和虚函数在内存中的位置
  9. 如何成为Emacs高手,像神一样使用编辑器
  10. 区块链软件公司:什么时候区块链技术?