使用 Wget 完成自动 Web 认证(推 portal)

引言

近日接触到一项实现 web 自动认证的小任务,该任务原打算通过代码模拟整个认证过程,但后来认识到这不过是重复造轮子,干嘛不用现成的经典命令行工具 -- Wget?尽管其 HTTP 支持有限,但够用了!

铺垫

任务虽小,五脏俱全,这里铺陈相关知识点如下:

一、Web认证方式

A. Http协议内建的认证方法
1. Http Basic Authentication (Http基本认证)
2. Digest Authentication (摘要式身份认证)
摘要式认证是一种基于challenge-response的认证模式
B. Form-based
基于Form的认证方式是高度可定制,也是目前用的最多的一种认证方式。流程简介:
1. 客户端通过一个form,把用户名和密码post给服务端
2. 服务端通过一些逻辑来判断认证是否有效。
3. 如果认证成功,服务器返回一个cookie(一个能唯一确认客户端的cookie,比如sessionId),用于客户端接下来的访问。如果认证失败,会提示用户进行重新输入用户名密码再次认证。
特点:
    *. 高度可定制:可以根据自己的需要来实现认证逻辑。
    *. 基于应用:此种认证方式是基于应用而不是内建于http协议或者浏览器的
    *. 服务器端要有一个保存客户端信息的地方,比如session。
    *. 客户端要有一个cookie来表明自己的身份,一般是username和一个cookie值(比如sessionId)的组合。
    *. 客户端cookie的生命周期和安全性息息相关。比如现在很多站点都支持“remember me”,其实就是在服务器端remember session并在客户端remember cookie。有些站点为了更好的安全性,用这种方式登录时,如果要执行一些重要的操作比如改密码,会要求客户用用户名和密码的方式重新登录
C. 证书认证(安全性相对较好)

二、基于Form的认证

如上所述,cookie 是服务器端用来跟踪客户登录状态的关键所在,所以要重点关注 cookie 的正确性。下面列出一些可能的检查点:

很多站点会在登录页面设置特殊 cookie 以确保你是通过登录页面进来的;有些站点会通过脚本来验证这不是自动登录,并记录进 cookie,可以通过分析脚本或暴力复制来避开;服务器常常会通过 referer 地址来判断上一页是从哪里来的;一些站点通过 UA 来识别浏览器支持

三、认识 cookie

要理清 session 和 cookie 的关系,这涉及后面 wget 的选项设置

cookie分为二种
1,以文件方式存在硬盘空间上的长期性的cookie(persistent cookies)
2,停留在浏览器所占内存中的临时性的cookie(session cookie)

浏览网站时,你会经常发现网站登录的地方,会有提示,问你是不是要记住自己的登录状态,像这种情况,登录时填写的一些信息会被以文件的方式存放在客户端的硬盘上。
当用户登录后,session会在cookie端产生一个session_id,这个session_id是存于浏览器所占用的内存当中。当你关闭浏览器后,session_id 随之消失。

cookie采用的是在客户端保持状态的方案,它是客户端的会话状态的一种储存机制。它是服务器在本地机器上存储的小段文本或是内存中的一段数据,并随每一个请求发送至同一个服务器。IETF RFC 2965 HTTP State Management Mechanism 是通用cookie规范。网络服务器用HTTP头信息向客户端发送cookies,在客户终端,浏览器解析这些cookies并将它们保存为一个本地文件,或者本地内存中数据,它会自动将同一服务器的任何请求缚上这些cookies,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制借助于cookie机制来达到保存标识的目的,这样就可以解决HTTP协议无状态的缺陷。浏览器的cookie被禁用后,session需要用get方法的URL重写机制,或使用POST方法提交隐藏表单的形式来实现。

关于 session

session是一种服务器端的信息管理机制,它把这些文件信息以文件的形势存放在服务器的硬盘空间上,这种情况是默认的,可以用memcache把这种数据放到内存里面。请参考web集群时利用memcache来同步session

当客户端向服务器发出请求时,要求服务器端产生一个session时,服务器端会先检查一下,客户端的cookie里面有没有session_id,是否已经过期。如果有这样的session_id的话,服务器端会根据cookie里的session_id把服务器的session检索出来。如果没有这样的session_id的话,服务器端会重新建立一个。PHPSESSID是一串加了密的字符串,它的生成按照一定的规则来执行。同一客户端启动二次session_start的话,session_id是不一样的。

session的失效时间要分两方面来看:浏览器端和服务端。对于浏览器端而言,session与浏览进程直接相关,进程关闭时,session也随之消失;而服务器端的session失效时间一般是人为设置的,目的是能定期地释放内存空间,一般的设置为当会话处于非活动状态达20或30分钟时清除该 session,所以浏览器端和服务端的session并非同时消失

四、Wget 的 HTTP 常用选项

--http-user=USER   设定HTTP用户名为 USER
--http-passwd=PASS   设定HTTP用户名为PASS,如果Web服务器需要指定用户名和口令,用这两项来设定;
--proxy-user=USER   设置代理用户
--proxy-passwd=PASS    设置代理密码,如果代理服务器需要输入用户名和口令,使用这两个选项;
--no-cache  不允许服务器端的数据缓存
-E, --html-extension       将所有text/html文档以.html扩展名保存
--ignore-length  忽略服务器发来的 `Content-Length' 头域
--header=STRING        在headers中插入字符串 STRING
--referer=URL        在HTTP请求中包含 `Referer: URL'头
-s, --save-headers   保存HTTP头到文件
-U, --user-agent=AGENT   设定 User Agent 的名称为AGENT而不是默认 Wget/VERSION
--no-http-keep-alive   不使用 HTTP 持久链接
--no-cookies    不使用 cookies.
--load-cookies=FILE   在开始会话前从文件 FILE 中加载cookie
--save-cookies=FILE   在会话结束后将 cookies保存到 FILE文件中
--keep-session-cookies   和 --save-cookies 一起使用(见 session 与 cookie 的关系)
--post-data=string
--post-file=file   使用POST方法提交 STRING 或 FILE 内容(若string太长可用file来缩短命令行长度)。FILE 只能是普通文件;特殊字符使用  percent-encoding;--header 可有多条,但 --post 选项只能有一个

实现

1)首先用抓包工具捕获完整的认证过程,可以用一般工具 WireShark,可以用专用工具 HttpAnalyzer/Fiddler,也可用轻量级的 Live HTTP Headers(firefox 扩展), Chrome 自带HTTP请求查看功能,HttpWatch(IE 插件,收费)

2)用 wget 选项模拟完整的请求过程

提示:有些页面的访问需要登录,即需要通过验证的 cookie。一般过程:post 登录、保存cookie,然后访问这些页面时带上cookie

wget --post-data="user=user1&pass=pass1&submit=Login" --save-cookies=cookie.txt --keep-session-cookies http://domain.com/login.php
wget --load-cookies=cookie.txt http://domain.com/path/page_need_login.php
其它选项根据抓取的 HTTP 请求内容来添加,如 referer 地址,UA,附加 header

3)如果有 wget 无法满足的特殊需求,可以试试 perl + LWP 模块(Library for WWW in Perl)

参考文献

1. GNU Wget Manual:HTTP Option

2. 老生常谈session,cookie的区别,安全性

3. GET和POST的真正区别

posted @ 2012-07-21 21:03  借筏度岸  阅读(10722)  评论(0编辑  收藏  举报