作者:玄魂
前置知识:c# http协议
本系列导航http://www.cnblogs.com/xuanhun/archive/2008/10/25/1319523.html
安全技术区http://space.cnblogs.com/group/group_detail.aspx?gid=100566
前言
web安全实践系列主要是对《黑客大曝光——web应用安全机密与解决方案(第二版)》的内容做的实践研究和部分编程实现。所以如果您能完全理解那本书可以跳过本文章。
正文
关于http编程我们可以采取套接字的方式遵循http协议来做。我采用的C#,对于http编程微软提供了已经封装好的类,WebRequest,WebResponse,HttpWebRequest,HttpWebResponse是常用的几个类,关于这些类的详细介绍请参考博客园内的其他文章,我只简单介绍我所用到的HttpWebRequest,HttpWebResponse类。抛砖引玉,因为做个好的http程序也是需要一定时间的,我这里给出的不是成型的工具,只是一个简单的例子,时间有限,望各位见谅。
HttpWebRequest类
HttpWebRequest 类对 WebRequest 中定义的属性和方法提供支持,也对使用户能够直接与使用 HTTP 的服务器交互的附加属性和方法提供支持。
不要使用 HttpWebRequest 构造函数。使用 WebRequest.Create 方法初始化 HttpWebRequest 的一个新实例。如果 URI 的方案是 http:// 或 https://,则 Create 将返回 HttpWebRequest 实例。
GetResponse 方法向 RequestUri 属性中指定的 Internet 资源发出同步请求并返回包含该响应的 HttpWebResponse 实例。可以使用 BeginGetResponse 和 EndGetResponse 方法对 Internet 资源发出异步请求。
当要向 Internet 资源发送数据时,GetRequestStream 方法返回用于发送数据的Stream实例。BeginGetRequestStream 和 EndGetRequestStream 方法提供对发送数据流的异步访问。
下面的示例为 URI http://www.contoso.com/ 创建 HttpWebRequest。
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/");
此类包含对 WebResponse 类中的属性和方法的 HTTP 特定用法的支持。HttpWebResponse 类用于生成发送 HTTP 请求和接收 HTTP 响应的 HTTP 独立客户端应用程序。
注意:不要混淆 HttpWebResponse 和 HttpResponse;后者用于 ASP.NET 应用程序,而且它的方法和属性是通过 ASP.NET 的内部 HttpResponse 对象公开的。
决不要直接创建 HttpWebResponse 类的实例。而应当使用通过调用 HttpWebRequest.GetResponse 所返回的实例。
通过调用 GetResponseStream 方法,以 Stream 的形式返回来自 Internet 资源的响应的内容。
下面的示例返回 HttpWebRequest 的 HttpWebResponse:
HttpWebRequest HttpWReq = (HttpWebRequest)WebRequest.Create("http://www.contoso.com");
HttpWebResponse HttpWResp = (HttpWebResponse)HttpWReq.GetResponse();
// Insert code that uses the response object.
HttpWResp.Close()
URI 是 Internet 上可由应用程序使用的资源的简洁表示形式。Uri 类定义了属性和方法来处理 URI,包括分析、比较和组合。Uri 类属性是只读的,修改 Uri 实例需使用 UriBuilder 类。
Uri 类只存储绝对 URI(例如"http://www.contoso.com/index.htm")。相对 URI(例如"/new/index.htm")必须相对于基 URI 展开,这样才是绝对的。提供了 MakeRelative 方法在必要时将绝对 URI 转换为相对 URI。
URI 由转义编码存储为规范化 URI,所有 ASCII 值大于 127 的字符都被替换为它们的等效十六进制数。为使 URI 具有规范化格式,Uri 构造函数执行以下步骤。
使用 ToString 方法,可以将 Uri 类的内容从转义编码的 URI 引用转换为可读的 URI 引用。
一些 URI 包括段标识符或查询。段标识符是 URI 中跟在数字符号 (#) 后的任何文本,存储在 Fragment 属性中。查询信息是 URI 中跟在问号 (?) 后的任何文本,存储在 Query 属性中。
注意:URI 类支持使用以下格式的 IP 地址:四组表示法的 IPv4 协议和冒号分隔的十六进制 IPv6 协议。请记住在 IPv6 地址两边括上方括号,如 http://[::1]。
下面的示例创建 Uri 类的实例,并用它来创建 WebRequest。
Uri siteUri = new Uri("http://www.contoso.com/");
WebRequest wr = WebRequest.Create(siteUri);
程序示例说明
在界面设计上,用一个textbox控件来输入地址,三个combobox控件提供请求方式和编码方式,连续发送次数的选择,因为不同的服务器可能支持不同的请求方式,不同的页面也可能是不同的编码方式。
另外两个textbox控件分别用来显示头信息和内容信息。
(1)信息处理类ProcessInfo。我们把用户输入的各种参数传给该类,由它负责发送请求和接收响应。下面给出的主要的函数,结合代码做说明。
/// <summary>
/// 发送请求接受响应
/// </summary>
/// <param name="tb">显示头信息的TextBox</param>
/// <param name="ta">显示内容信息的TextBox</param>
/// <param name="method">请求方式</param>
/// <param name="codemethod">编码方式</param>
public void SendInfo( TextBox tb,TextBox ta,string method,string codemethod)
{
//首先我们创建HttpWebRequest的实例,用来发送请求。
hwr = (HttpWebRequest)WebRequest.Create(uri);
//然后设置它的请求方式。
hwr.Method = method;
CodingMethod = codemethod;
try
{
//创建HttpWebResponse的实例
response = (HttpWebResponse)hwr.GetResponse();
//因为response.Headers包含了我们想要的头信息,而它是WebHeaderCollection类型
//所以我们创建WebHeaderCollection实例myheaders,然后把它转化成字符串。
WebHeaderCollection myheaders = response.Headers;
f1.AddInfo(myheaders.ToString(), ta);
// GetResponseStream()方法,获取的信息是返回的内容信息。
Stream resStream = response.GetResponseStream();
int count = resStream.Read(buf, 0, buf.Length);
f1.AddInfo(getString(buf), tb);
hwr.Abort();
resStream.Close();
response.Close();
}
catch(Exception e)
{
MessageBox.Show(e.ToString());
}
finally
{
Thread.CurrentThread.Abort();
}
}
(2)form1的主要函数。
这是点击button按钮的事件处理函数,获得用户设置的各种参数,然后启动单独的线程调用信息处理类ProcessInfo的相关方法。
private void button_send_Click(object sender, EventArgs e)
{
// 部分代码省略
for (int i = 0; i < Int32.Parse(this.comboBox_sendtiems.SelectedItem.ToString()); i++)
{
Thread t = new Thread(new ThreadStart(GetInfo));
t.Start();
}
}
/// <summary>
/// 把参数传入ProcessInfo类的处理函数
/// </summary>
private void GetInfo()
{
ProcessInfo pi = new ProcessInfo(textBox_uri.Text,this);
pi.SendInfo(textBox_content, textBox_head, combox1, combox2);
}
/// <summary>
/// 用于异步调用向textbox中添加响应信息
/// </summary>
/// <param name="info"></param>
/// <param name="myt"></param>
public void AddInfo(string info,TextBox myt)
{
//判断是否为跨线程调用
if (myt.InvokeRequired)
{
SetInfoCallback sic = new SetInfoCallback(AddInfo);
this.Invoke(sic, new object[] { info,myt });
}
else
{
myt.Text += info;
}
}
好了,这个简单的例子可能不能给你太多的启示,但是我的这个系列还得继续向前走。更多的编程实践,如果你做了,一定要分享哦,独乐乐不如众乐乐吗!
下面把源代码附上:http://files.cnblogs.com/xuanhun/源代码.rar