不要被.Net的假提交蒙骗了

目标

过程比较曲折,还是从头说起吧,事情的起因是这样的:现在不是主要在Ubuntu下工作么,但是单位的办公系统却只能使用ie,原因是因为要使用一个activex控件来读取一个加密锁,然后才能利用加密锁内的数据登录进入系统。而在测试系统中,我可以使用用户名+密码的方式进入系统,之后基本上所有的页面在firefox下操作也都正常。综上所述,只要能够跳过“登录”这一关,我就不用再启动笨重的vmware去运行ie使用这套办公软件了,直接利用firefox就可以了。ok,现在我的目标已经确定,下面是主要的解决思路。

解决思路

在firefox下使用过del.icio.us、furl等服务的应该都知道,他们都可以在firefox的书签工具栏上生成一个按钮,而只要点击这个按钮,就可以把当前页面存入美味书签或者记入furl收藏,甚至可以读取到当前页面上的部分内容。其实,这些书签工具栏上的按钮和普通的书签没有本质区别,只是别人以http://开头,他们以javascript:开头罢了。看看这个小例子:拖动下面这个链接到书签工具栏,然后点击执行一下,看看会发生什么?其实把网址直接拖动到书签工具栏或者Bookmarks菜单下也是一样能够保存的,因为他们本来就是一类东西。

拖动我到书签工具栏,然后点击执行一下,看看会发生什么?

(在书签工具栏的按钮上面点击鼠标右键,然后选“Delete”就可以删除了。)

同理,activex只是读取加密锁的工具,最终还是要把读出的数据通过表单post到服务器上进行验证,所以,只要我们能够“跳过”activex读取这一步,直接把加密锁中的数据post到服务器上,就能够形成一样的效果。

获得加密锁数据

很简单,问开发人员要就是了,还有一种做法就是仔细研究客户端的脚本然后改写为本地模式然后自己读,当然对于有些带有加密性质的activex控件是无效的。幸好开发人员很乐意提供我加密锁的数据,因为除了锁上的显式数据以外,另外还有一个校验码,同时存放在加密锁和服务器上,就像“虎符”一样,碰对了才有效,所以在小范围内实施我这种行为基本上不会带来什么安全问题。

“伪”读取并提交数据

也不复杂,前提是观众要对上面那个书签工具栏上的按钮的例子有比较清楚的理解,这里我就直接贴代码好了:

javascript:(function(){document.Form1.username=’coolboy’; document.Form1.password=’ooxx’; document.Form1.submit();})();

我当然不会贴出真实的数据啦,上面的例子就是模仿一个登录表单,通过js向表单中写入数据,最后直接调用表单的submit方法。由于是这些内容是要填在书签的“地址”一栏中的,所以是一长行的形式。

实战!

像上面那个例子一样,在js中对表单对象赋值,然后调用表单的submit方法,然后运行。。。。咦?怎么没有效果?页面好像只是刷新了一下,然后就没有变化了,既不是已经成功登录的样子,也不是登录数据错误的样子,好像、好像就仅仅是刷新了一下!

费劲周折,终于了解到了真实原因,原来是被.net的小把戏给耍了:

.net为开发人员提供了很多方便的工具,其中包括在“服务端”运行的web form控件,在开发的时候他们和普通的html控件没有大的区别,但是却能够很方便的让开发人员对其属性和方法进行设定。然后在实际运行生成html页面的时候,.net引擎会将他们转化为标准的html表单代码,并且利用__VIEWSTATE保存状态数据。

而我们刚刚看到的“刷新”是什么呢?原来是这样:首先我们通过js进行赋值的操作是没有问题的,值被正确设定,然后调用表单的submit方法也没有错,数据也正确的提交到服务端了,但是,当服务器端接受到post的数据之后,并没有按照正常的post方法来进行处理,而是另外一套方法。为什么会这样呢?因为我们在客户端收到的html代码中看到的form,input等控件,都是带有runat=”server”属性的,也就是设定了要在服务器端执行。我们当然看不到实际的runat=”server”,因为在生成页面时就已经转换成了标准的html代码。而当服务器端接受到有关runat=”server”控件的操作的时候,却不会按照正常的get、post来操作,而是使用在服务器端代码中设定好了的方法来执行操作。本例中,由于使用js手工提交的数据并没有和服务器端设定的方法“吻合”在一起,导致服务器端没有进行任何操作,又原原本本的把页面送了回来,所以,我们看到页面“刷新”了一下。我们以为表单被提交了,就会被服务端正常的处理,却没有想到.net引擎偷懒什么也没干,蒙蔽了我们的双眼。

现在,我终于明白,为什么在有些.net开发的应用中,输入完数据直接敲回车是不会提交的,必须用鼠标点击“提交”按钮才行,看来.net的威力在不成熟的开发者手工也不过如此。

关于上述的.net实现机制,可以参考: asp.net用户控件中的Button,在直接回车的时候不提交表单,如何办? 关于前台调用后台事件__doPostBack函数 (论坛答疑点滴)__doPostBack()无效?

排除问题,胜利!

虽然道理是绕了一个圈子,但是解决方法却是无比的简单:

javascript:(function(){document.Form1.username=’coolboy’; document.Form1.password=’ooxx’; document.Form1.Button_Submit.click();})();

没错,就是由原来的调用表单的submit方法(以前常用),变成了直接调用submit按钮的click方法,问题顺利解决!但是究其深层次的道理,还是要看看上面几篇参考中关于doPostBack函数的解释,应该能够明白一些。

废话

我们这些喜欢使用linux系统的人,在广大使用windows系统的同志们心中,总是那么的“特别”,其实他们不知道,在很多技术细节上,真正“特别”的却多是windows产品。比尔大叔的风格,就是把原本就有标准解决方法的东西,增加一些华丽的“方便”功能,然后用只有微软才能够解释清楚的方式,包装成为“方便”开发人员的“工具”,在赚进大把的钞票的同时,还让广大开发人员对微软产品产生了无比的依赖性。我想这也许是微软始终无法真正创造底层技术标准的原因吧。就像黑客帝国一样,只要你身在matrix当中,不管你作什么,都只是matrix的一个“子程序”,只有跳出矩阵,才能看清楚这个世界。

4 thoughts on “不要被.Net的假提交蒙骗了”

  1. hi,看到你在openfans注册了,现在开通了blog导入的功能,你能将这个blog提交吗。看你对ubuntu挺有研究,能在openfans推荐下不。

Leave a Reply to pesome Cancel reply

Your email address will not be published. Required fields are marked *