悲剧了,发现写完这篇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. Knockout应用开发指南 第六章:加载或保存JSON数据

    原文:Knockout应用开发指南 第六章:加载或保存JSON数据 加载或保存JSON数据 Knockout可以实现很复杂的客户端交互,但是几乎所有的web应用程序都要和服务器端交换数据(至少为了本地 ...

  2. mybatis 打印SQL语句

    在log4j文件中配置 log4j.rootLogger=DEBUG log4j.logger.com.ibatis=DEBUG log4j.logger.org.mybatis=DEBUG  

  3. UVA 12263 Rankings(拓扑排序)

    给出一个n个数的序列1,然后有m个改动(a, b),在序列2中a跟b在序列中的相对顺序改变.求符合题意的序列2. 题中说道如果一个数的位置不确定,则输出‘?' ,仔细想想,这种情况是不会存在的,因为在 ...

  4. MYSQL经常使用命令列表

    MYSQL经常使用命令列表 1.系统管理 mysql -h主机地址 -uusername -p 连接MYSQL(在mysql/bin) exit 退出MYSQL命令 mysqladmin -uuser ...

  5. oracle之spool详细使用总结(转)

    今天实际项目中用到了spool,发现网上好多内容不是很全,自己摸索了好半天,现在总结一下. 一.通过spool 命令,可以将select 数据库的内容写到文件中,通过在sqlplus设置一些参数,使得 ...

  6. mmc生产任务分配问题

    mmc生产任务分配问题,本题目简单.

  7. 第二期“晋IT”分享成长沙龙

    本期主题:微信.打造品牌个体 报名方式:关注微信.回复"我要成长" "晋IT"沙龙费用:全程免费 "晋IT"沙龙文化:共通 共融 合作共赢 ...

  8. Spring Bean的作用域(转)

    Spring Bean的作用域 .singleton  [单例] eg:<bean id="personService" class="com.yinger.ser ...

  9. 重新想象 Windows 8 Store Apps (2) - 控件之按钮控件: Button, HyperlinkButton, RepeatButton, ToggleButton, RadioButton, CheckBox, ToggleSwitch

    原文:重新想象 Windows 8 Store Apps (2) - 控件之按钮控件: Button, HyperlinkButton, RepeatButton, ToggleButton, Rad ...

  10. 数据结构读书笔记(二)(C语言)

    (一)循环链表 存储类型 typedef struct LNode { ElemType data; struct LNode *next; }; typedef struct LNode *Link ...