悲剧了,发现写完这篇blog没有配上这个格调超高的标题。

 
1.0问题背景
现在要实现一个带验证码网站的的自动登陆功能。验证码识别过程不再这篇文章的讨论之中。(之后有篇文章我会详细的总结验证码的识别过程)。现在问题来了,怎么拿到你本次请求登陆页面的验证码图片?
2.0方案分析
现在有几种思路:
(1)请求登陆页面,截取验证码图片,类似截屏,seleinum,webbrower的DrawToBitmap()等。
(2)还是webbrower,将图片复制到剪切板在从剪切板中搞出来
  • HTMLControlRange rang = (IHTMLControlRange)body.createControlRange();
  • IHTMLControlElement imge;
  • imge = (IHTMLControlElement)img.DomElement;
  • rang.add(imge);
  • rang.execCommand("Copy", false, null);
  • Image image = Clipboard.GetImage();
(3)前两种都是用一种类似浏览器的软件帮我们完成登陆页面的请求,下面我们来深入的分析下请求登陆页面这个过程是什么样子的。第一次请求这个页面
 
 
在浏览器中我们看到的是这个页面,我们用fidder抓包发现,我们关系的请求只有两次。
 
 
所以,我们第三种思路也来了。那我们用webclient或httpwebrequset模拟这两次请求不就完事了?一次请求登陆页面,一次请求验证码,然后模拟表单提交,多简单的事!
 
悲剧 就发生在这:你模拟请求的验证码输入后总是不对,一大堆的人都说你对验证码发了二次请求,你获得的验证码是上一次的!!有的人一想,我靠,是这么回事啊,怪不得不行呢,这方法不行啊。
 
大家仔细想一想,我怎么对验证码发送二次请求了?老子一共模拟两次请求,一次请求登陆页面,一次请求验证码,就一次好吗!所以这种说法是错误的,我们从头来分析:
 
第一次是请求这个登陆页面,这是请求头
这是response头:
我们发现服务器向客户端写了一个cookie;之后我们讨论这个cookie的作用。
 
我们继续观察第二请求,该请求是怎么发出来的呢?我们现在都应该知道了,第一次请求服务器返回的是这个登陆页面的html代码,对吧,浏览器拿到这个html代码后它就要渲染了,就是在浏览器给我画这个漂亮的页面。
 
当它看到这串代码时 <img width="60" height="25" src='/cas/codeimage/>它就认为,这是一个图片啊,我赶紧去按图片地址去拿吧,晚了就玩了,这样,他就发送了第二个请求。我们来看报文:
 
 
发现了什么,请求报文中竟然带了cookie。这就要涉及到cookie的工作原理了,cookie是写在客户端的,就是一个键值对,就是是写在你浏览器对应的cookie存放位置,cookie是不能跨浏览器的,360浏览器的cookie你google浏览器是不能玩的。
 
cookie是不能跨域的,就是不能a.com的cookie不能提交到c.com.而且cookie在同一域名下,会自动提交的,这也说明了第二次请求为什么会无缘无故的多了个cookie。cookie的作用path,过期时间等其他参数这里就不说了。
 
 
好了,关键的东西我们都发现了,就是这个cookie搞的。它到底是什么鬼?是干啥的?我们来分析下验证码的实现机制,不是讲怎么画出来的,用户去请求验证码,服务器生成验证码字符,然后把他存在session里,另外又把这个字符串画到图片上返回给浏览器。有人问session又是什么鬼?session也是一个键值对,跟cookie不同的是,session是存在服务器端的。服务器端有个session池,里面放的就是一个一个的键值对。
 
我们填完了验证码,提交到服务器,服务器开始判断你填的对不对,他怎么判断的呢?逗比,服务器不是有session吗?一比不就得了嘛!怎么比?服务器的session多了去了,所以只能拿着键,去找值,那这个值和你提交过来的值比。那么问题来了,键是那来的?你什么时候提交过来的?见鬼了?相信大家都已经想到了,这个键就是刚才那个cookie的值。
 
这样大家也就明白了,原来session是通过cookie实现的啊,你以为呢?
 
 
到这里,我们就找到第二次模拟请求验证码过程发生的问题了。原来是这次请求没有带上第一次请给的cookie。你没带,说明你提交的键是null,服务器却是真实有的,当然每次请求都错误 了。
 
知道错误地点了,这问题也就解决了:提交的时候直接带上第一次的cookie不就结了。简单代码:
CookieContainer cookiesContainer = new CookieContainer();
if (response1.Cookies.Count > 0)
{
cookiesContainer.Add(response1.Cookies);
}
 
requst2.CookieContainer =cookieContainer;
 
3.0总结
这里要说明下,这个cookie是到底什么时候给你写到客户端?按道理来讲,这个cookie这与你的验证码有关,你访问验证码图片时候,给你写个才对。但这个实验网站他访问登陆页面就给你写了,到你访问验证码页面时候,估计是他先判断你有没有写cookie,没写的话给你写上。所以这cookie在哪还得自己抓包看。另外还有很多隐藏域的值参与验证,分析的时候也要注意。
 
这还有个问题:服务器设定验证码session的时候,键直接设置为"VCde",还用从cookie里找干嘛?针对一个用户来说,这样是可以的,如果多个用户同时访问的话,会发生什么情况。A刚拿到验证码,VCde存的是A的字符。这时候B来登陆,VCde立马变成B的字符,A兴致勃勃的填完了去登陆,验证码错误!所以,cookie中村的不是vcode的key,他是sessionId,服务器中是session空间像一个柜子,sessionid就是那个柜子的钥匙,而柜子里存的才是你网session中存的数据,当然了,验证码就存在柜子里。
 
http://www.cnblogs.com/cnduan/p/4344097.html

从session实现机制分析模拟请求验证码的可行性(转)的更多相关文章

  1. Session Timer机制分析

    Session Timer机制分析 功能介绍 会话初始化协议(SIP)并没有为所建立的会话定义存活机制.尽管用户代理可以通过会话特定的机制判断会话是否超时,但是代理服务器却做不到这点.如此一来,代理服 ...

  2. 分布式session共享机制分析

    使用配置: 1.在pom文件中引入spring-session的jar包 <!--springsession--><dependency><groupId>org. ...

  3. zookeeper session tracker机制分析

    说到zookeeper session管理 ,免不了要问 什么是session? session id/session是如何产生的? session 信息如何存储? 本文以session tracke ...

  4. Flask框架(三)—— 请求扩展、中间件、蓝图、session源码分析

    Flask框架(三)—— 请求扩展.中间件.蓝图.session源码分析 目录 请求扩展.中间件.蓝图.session源码分析 一.请求扩展 1.before_request 2.after_requ ...

  5. Tesseract-OCR牛刀小试:模拟请求时的验证码识别

    原文:http://yaohuiji.com/tag/tesseract%EF%BC%8Cocr%EF%BC%8C%E9%AA%8C%E8%AF%81%E7%A0%81/ 有个邪恶的需求,需要识别验证 ...

  6. 获取登录验证码失败及前后端不同域导致session丢失问题分析记录

    前言 前两周在把兄弟公司的几个服务部署到我们公司测试环境服务器的时候又遇到了不少问题,因为是前后端分离的项目,所以这次也同样遇到了跨域问题,解决方式也跟上一回的不一样,这里就再来分析记录一下. 登录验 ...

  7. c# JD快速搜索工具,2015分析JD搜索报文,模拟请求搜索数据,快速定位宝贝排行位置。

    分析JD搜索报文 搜索关键字 女装 第二页,分2次加载. rt=1&stop=1&click=&psort=&page=3http://search.jd.com/Se ...

  8. 【教程】手把手教你如何利用工具(IE9的F12)去分析模拟登陆网站(百度首页)的内部逻辑过程

    [前提] 想要实现使用某种语言,比如Python,C#等,去实现模拟登陆网站的话,首先要做的事情就是使用某种工具,去分析本身使用浏览器去登陆网页的时候,其内部的执行过程,内部逻辑. 此登陆的逻辑过程, ...

  9. Linux信号(signal) 机制分析

    Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...

随机推荐

  1. (转载)浅析error LNK2001: unresolved external symbol "public: __thisc...

    学习VC++时经常会遇到链接错误LNK2001,该错误非常讨厌,因为对于      编程者来说,最好改的错误莫过于编译错误,而一般说来发生连接错误时,      编译都已通过.产生连接错误的原因非常多 ...

  2. (40)JS运动之右下角悬浮框

    <!DOCTYPE HTML> <!-- --> <html> <head> <meta charset="utf-8"> ...

  3. UNIX网络编程卷1 server程序设计范式7 预先创建线程,以相互排斥锁上锁方式保护accept

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.预先创建一个线程池.并让每一个线程各自调用 accept 2.用相互排斥锁代替让每一个线 ...

  4. 动态加载资源文件(ResourceDictionary)

    原文:动态加载资源文件(ResourceDictionary) 在xaml中控件通过绑定静态资源StaticResource来获取样式Style有多种方式: 1.在项目的启动文件App中<App ...

  5. nginx subrequest演示示例程序

    只有简单subrequest应用演示示例. nginx.conf文件: #user nobody; worker_processes 1; #error_log logs/error.log; #er ...

  6. ostringstream使用

    ostringstream使用 [本文来源于]http://www.builder.com.cn/2003/0304/83250.shtml http://www.cppblog.com/alanto ...

  7. Windows Phone开发(24):启动器与选择器之发送短信

    原文:Windows Phone开发(24):启动器与选择器之发送短信 本节我们通过一个简单的发送短信示例来演示一下如果配合使用PhoneNumberChooserTask和SmsComposeTas ...

  8. iframe属性參数

    iframe属性參数 当点击一个子页面的链接时, 怎样将还有一个子页面嵌入到当前iframe中 仅仅要给这个iframe命名就能够了. <iframe width=420 height=330 ...

  9. 新书《iOS8 Swift编程指南》货架

    颐和园的新书出版. 链接:http://www.amazon.cn/dp/B00YOQSYAO 这本书从去年开始7可能开始写.今年1完成这个月的第一稿,经过多次修改,今天,最后的正式出版,欢迎大家指正 ...

  10. wamp无法登录phpmyadmin问题

    文章来源:PHP座谈会 地址:http://bbs.phpthinking.com/forum.php? mod=viewthread&tid=163 第一步.用navicat确认一下,自己的 ...