使用C#实现网站用户登录

我们在写灌水机器人、抓资源机器人和Web网游辅助工具的时候第一步要实现的就是用户登录。那么怎么用C#来模拟一个用户的登录拉?要实现用户的登录,那么首先就必须要了解一般网站中是怎么判断用户是否登录的。

HTTP协议是一个无连接的协议,也就是说这次对话的内容和状态与上次的无关,为了实现和用户的持久交互,网站与浏览器之前在刚建立会话时将在服务器内存中建立一个Session,该Session标识了该用户(浏览器),每一个Session都有一个唯一的ID,第一次建立会话时服务器将生成的这个ID传给浏览器,浏览器在接下来的浏览中每一个发向服务器的请求中都将包含该SessionID,从而标识了自己的身份。

服务器上是使用内存来保存Session中的信息,那么浏览器又使用什么来保存服务器分配的这个SessionID了?对,是Cookie。在刚建立会话时浏览器向服务器的请求中将不包含SessionID在Cookie中,服务器就认为是一个全新的会话,从而在服务器上分配一段内存给该Session用,同时将该Session的ID在Http Header中使用Set-Cookie发送给浏览器。

现在原理已经搞清楚了,那么我们就来实现一个网站的登录嘛,这里就以盛大纵横天下的登录为例。

要写这种面向协议的网络程序,抓包工具是少不了的,我们首先是要使用抓包工具分析在普通浏览器中登录时发送和接收的内容才好进一步使用C#来模拟浏览器发包。抓包工具很多,看个人爱好吧,我主要用的是HTTP Analyzer,专门针对HTTP的,太强的抓包工具把什么协议的包都抓出来反而不利于我们分析。

1.最好能清除IE的所有Cookie记录,以免对抓包分析造成影响,然后开启抓包程序。

2.在IE中输入http://zh.sdo.com/web1.0/home/fastlogin.asp 这个快速登录地址,我们将看到已经抓到了很多请求和响应的包。

3.输入用户名和密码,点击登录,IE中正常登录,停止抓包,我们要的所有信息都被抓取好了。如图:

image

4.盛大的登录机制还是属于比较复杂的,中间涉及到好几个服务器,经过分析得知(这个就是一个比较漫长的过程了,具体网站具体分析,这个分析过程我就不写了)纵横天下的登录机制为:

1)IE请求https://cas.sdo.com:80/cas/login?service=http://zh.sdo.com/web1.0/home/index.asp页面,该页面给IE一个SessionID,比如Set-Cookie: ASP.NET_SessionId=avcbse55l5e03suqi4dx3555; path=/

2)IE同时在该HTTP的正文中得到一个ticket,这个ticket将在登录中有用,当然其他网站肯定不是这样做的,这里分析的是纵横天下的。location.href    =    http://www.sdo.com/login2.asp?lt=sd-1420e593-d2cf-4c9c-b249-07fe27932a21-2008-05-06_01%3a25%3a41.484&service=http%3a%2f%2fzh.sdo.com%2fweb1.0%2fhome%2ffastlogin.asp%3ftest%3d1; 这里lt参数就是我说的ticket了。

3)将获得的lt、用户名、密码还有一些其他的无关紧要的参数都Post到https://cas.sdo.com:80/cas/Login.PostTarget.aspx?service=http://zh.sdo.com/web1.0/home/fastlogin_after.asp 中,具体抓到的Post的数据如:warn=false&_eventId=submit&idtype=0&gamearea=0&gametype=0&challenge=3623&lt=sd-1420e593-d2cf-4c9c-b249-07fe27932a21-2008-05-06_01%3A25%3A41.484&username=studyzy&password=1234&ekey=&challenge=3623,这里我们就只关心lt,username,password这三个参数。

4)获取一个只有登录後才能访问的页面,测试是否登录成功。

5.好,整个登录机制我们已经分析完了,接下来就是考虑代码的实现了。在面向HTTP协议上,C#中有WebRequest、WebResponse、HttpWebRequest和HttpWebResponse等类。我们主要就基于这些类进行操作,当然完全基于Socket编程也可以,但是这里就没有这个必要了。

在不设置Cookie、PostData的情况下要获得一个页面的HTML的方法很简单:

public static string GetHtml(string URL)
        
{
            WebRequest wrt;
            wrt 
= WebRequest.Create(URL);
            wrt.Credentials 
= CredentialCache.DefaultCredentials;
            WebResponse wrp;
            wrp 
= wrt.GetResponse();
            
return new StreamReader(wrp.GetResponseStream(), Encoding.Default).ReadToEnd();
        }
 

 

当需要获得服务器返回的Cookie的话,可以通过wrp.Headers.Get("Set-Cookie")方法来获取。

如果需要将Cookie加入到请求另外还Post数据的话其实也很简单,只需要将httpWebRequest对象中设置ContentLength 和Request的Stream就可以了。

httpWebRequest.ContentLength = byteRequest.Length;
Stream stream;
stream 
= httpWebRequest.GetRequestStream();
stream.Write(byteRequest, 
0, byteRequest.Length);
stream.Close(); 

 

代码我就不都贴出了,我做了一个Demo在附件中,大家有兴趣研究的可以看一下。 /Files/studyzy/LoginSdoDemo.rar

代码中实现了盛大账号的登录,其实纵横天下的登录还没有完成,接下来还有选择具体服务器,将ticket转到具体服务器上再进行验证,原理也是一样的,我这里就不再累述了。

成功登录后,接下来我们只需要每次发送请求是跟上该Cookie,服务器就认为是登录的用户在操作了,接下来就可以随便灌水、Download资源了,具体要做什么就大家自己弄了,只需要在IE中操作一篇,抓包分析出来,用C#实现同样的发包就OK!

【出自博客园深蓝居,转载请注明作者出处】
posted @ 2008-05-06 02:31 深蓝 阅读(11975) 评论(50) 编辑 收藏

 回复 引用 查看   
#1楼 2008-05-06 08:05 LanYo      
学习
 回复 引用 查看   
#2楼 2008-05-06 08:21 大宋提刑官      
很有学习价值,谢谢楼主.
 回复 引用 查看   
#3楼 2008-05-06 08:22 李战      

 回复 引用 查看   
#4楼 2008-05-06 08:23 鬼不灵      
这样是可以的,不过你那个抓包工具,未免复杂些,我推荐iehttpheaders这个比较实用。 是的用WebRequest可以轻松实现外部表单提交!!关键是得到cookie,呵呵~~
 回复 引用 查看   
#5楼 2008-05-06 08:25 鬼不灵      
关键是找到真正的post地址,与cookie参数,呵呵~~
 回复 引用   
#6楼 2008-05-06 08:44 随风飘扬[未注册用户]
为什么不用 CookieContainer 呢?
 回复 引用 查看   
#7楼 2008-05-06 09:03 玉开      
路有很多条,都可以实现;我建议用webclient
 回复 引用 查看   
#8楼 2008-05-06 09:18 亚历山大同志      
如遇验证码又当如何?
 回复 引用 查看   
#9楼 2008-05-06 09:53 nicye      
--引用--------------------------------------------------
鬼不灵: 这样是可以的,不过你那个抓包工具,未免复杂些,我推荐iehttpheaders这个比较实用。 是的用WebRequest可以轻松实现外部表单提交!!关键是得到cookie,呵呵~~
--------------------------------------------------------
WebRequest 对部分对持久连接型网站支持得不好,严重到无法访问到目标。
Cookies 用它的确很好管理,就因为有个 CookieContainer,但它使用的不是标准的 Cookies。

 回复 引用 查看   
#10楼 2008-05-06 10:21 汉广      

遇到ssl怎么办,

 回复 引用 查看   
#11楼 2008-05-06 10:27 Jack Niu      
--引用--------------------------------------------------
亚历山大同志: 如遇验证码又当如何?
--------------------------------------------------------
对啊,如果遇到验证码怎么办? (我倒是有个笨办法,登陆时抓出图片,然后提示用户输入验证码。有了验证码后,一直保持这个连接,不要再次登陆,但不知道是否可行)

 回复 引用 查看   
#12楼 2008-05-06 10:27 nicye      
@汉广
http ssl 没啥用
用 sniffer 监视一下 http 包,自己用 socket 发包再看返回内容

 回复 引用 查看   
#13楼 2008-05-06 12:22 scotoma      
学到不少都是有用的.不过楼上的几位提到的 特别是验证码这个识别也是个麻烦的问题
 回复 引用 查看   
#14楼 2008-05-06 12:43 alisx      
刚好在学asp.net,好好学一下
 回复 引用 查看   
#15楼[楼主] 2008-05-06 13:48 深蓝      
@scotoma
验证码问题其实很简单,首先我们随便请求一个页面,建立一个会话,获得了SessionID,然后将SessionID作为Cookie去请求验证码生成的页面,那么我们可以获得服务器返回的Image流,使用C#将返回的流转换为图片显示出来,让用户输入用户名密码和图片上的验证码,然后将这些内容还有Cookie一起Post到服务器就可以正常登录了。该方法百试不爽!

 回复 引用 查看   
#16楼 2008-05-06 14:17 S.Sams      
关键得加载Cookie容器. new CookieContainer();
 回复 引用 查看   
#17楼 2008-05-06 15:31 nicye      
@深蓝
我以前也是像你这样做的,但后来让程序自动识别。

 回复 引用 查看   
#18楼 2008-05-06 15:40 天生俪姿      
不错支持下
 回复 引用 查看   
#19楼[楼主] 2008-05-06 15:45 深蓝      
@nicye
你太牛了,自动识别验证码!我曾经也尝试过,可惜失败了,识别率太低了。我想只有2种情况:1,你技术够牛把人都不一定能识别的验证码识别出来。2,你要识别的那个网站太垃圾,就是纯粹的字符数字,没有文字变形、混淆等干扰元素。

 回复 引用 查看   
#20楼 2008-05-06 16:21 nicye      
@深蓝
嗯,不是很麻烦的验证码

 回复 引用 查看   
#21楼 2008-05-06 17:56 镜涛      
mark
 回复 引用 查看   
#22楼 2008-05-06 19:15 簡簡單單..      

 回复 引用 查看   
#23楼 2008-05-06 20:20 汉城      
很有收藏价值
 回复 引用 查看   
#24楼 2008-05-06 23:32 Zhuang miao      
很好!!关键是学习到了思路~~谢过!!谢过!!回头好好研究研究~~~
 回复 引用 查看   
#25楼 2008-05-06 23:33 Zhuang miao      
收藏了!!
 回复 引用 查看   
#26楼 2008-05-07 00:39 李涛      
呵呵,思路不错.
 回复 引用 查看   
#27楼 2008-05-07 11:06 looping      
很强。。学习了
 回复 引用 查看   
#28楼 2008-05-07 11:51 HappyQQ      
学习,谢谢
 回复 引用 查看   
#29楼 2008-05-07 13:00 天生俪姿      
问下~!楼主的那个 图片预览的代码,就是移动图片或者链接上就会有相应网页链接或者图片的预览的代码。有没有给发一下呗~!

 回复 引用 查看   
#30楼 2008-05-31 21:13 长沙小能      
非常不错的说,努力学习中。
 回复 引用   
#31楼 2008-06-01 23:19 他山居士[未注册用户]
要摸拟discuz类网站比较困难,因为用户和密码都是加密,楼主是否进行一些探索?
 回复 引用 查看   
#32楼 2009-03-30 18:06 kkding      
楼主破到第几层了。

想问个问题,第一次提交amf给/GameP/flashservices/gateway.php,为什么反馈的是500错误。

我已经进到http://zhtx1x01.sdo.com/play.php
cookie已经提交给
PHPSESSID=aebca25a1f72083444bb9d4c5922ccbd
CAS_LOGIN_STATE=1

 回复 引用 查看   
#33楼 2009-11-04 21:59 wangpan      
我对这个很感兴趣 我现在急需做一个网站登录机,非常急

但是我看了这个还是不太明白

是不是群主可以帮我解决一下

我的
qq是864432850


同志们非常急

 回复 引用 查看   
#34楼 2009-11-04 22:08 wangpan      
@鬼不灵
那个我问下 这里的cookie到底有什么用

还有就是网站登录,一共有几方式,我是问服务器进行验证的过程有几种 ?




<form name="aspnetForm" method="post" action="Default.aspx" onsubmit="javascript:return WebForm_OnSubmit();" id="aspnetForm">
这种方式的又该怎么实现,他的onsubmit=了一个java方法

 回复 引用 查看   
#35楼[楼主] 2009-11-05 10:15 深蓝      
@wangpan
这个cookie一方面用于存储用户的一些个人信息,另一方面也存储了服务器分配给客户端的一个ID标识,用于标识一个会话。

 回复 引用 查看   
#36楼 2009-11-05 17:04 wangpan      
@深蓝

我可不可直接把必要的信息比如说用户名,密码,it等等 给他post过去 这之前是不是需要get一下连接一下要登陆的网页 ?

 回复 引用 查看   
#37楼 2009-11-05 17:04 wangpan      
@深蓝

我可不可直接把必要的信息比如说用户名,密码,it等等 给他post过去 这之前是不是需要get一下连接一下要登陆的网页 ?

 回复 引用 查看   
#38楼 2009-11-06 21:25 wangpan      
cookie怎么得到
我用了那种httprequest 和httpresponse
访问了一个网页,
但是我用抓包工具分析,没有发现有cookie 这是怎么回事,
能不能教我一种方法获得cookie

还有就是 我能不能直接 进行 post而越过cookie这一步呢

?

 回复 引用 查看   
#39楼[楼主] 2009-11-06 21:29 深蓝      
@wangpan
在第一次请求一个网站的页面时,系统返回的HTTP头里面就有Set-Cookie,这里就是给当前的客户端分配一个会话ID的,你可以通过解析服务器返回的响应的HTTP头来获得Cookie。
不能直接Post而跳过获得Cookie一步,这样服务器就不知道到底是哪台机器请求的。

 回复 引用   
#40楼 2009-11-08 18:28 威威[未注册用户]
楼主,能不能帮帮我啊,我用你的思路已经实现了一个网站的自动登陆,但是淘宝的自动登陆怎么也调不好啊你能帮我看下代码吗?

string getpage = "http://member1.taobao.com/member/login.jhtml?TPL_password=" + textBox2.Text(密码) + "&TPL_redirect_url=&TPL_username=" + HttpUtility.UrlEncode(textBox1.Text(用户名,汉字), Encoding.GetEncoding("GBK")) +"&_oooo_=&abtest=&action=Authenticator&actionForStable=enable_post_user_action&done=&event_submit_do_login=anything&from=&pstrong=2&yparam=";
HttpWebResponse res1 = (HttpWebResponse)req1.GetResponse();
HttpWebRequest req1 = (HttpWebRequest)WebRequest.Create(getpage);

req1.Method = "GET";

req1.AllowAutoRedirect = false;

Co.Add( res1.Cookies);






if (res.StatusCode == HttpStatusCode.Moved || res1.StatusCode == HttpStatusCode.Found || res1.StatusCode == HttpStatusCode.Redirect)
{
Locationadress = res1.Headers.Get("Location");
richTextBox1.AppendText("登陆成功且转移地址为:" + Locationadress + "\r\n");
HttpWebRequest wrt2;
wrt2 = (HttpWebRequest)WebRequest.Create(Locationadress);
wrt2.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)";
wrt2.Method = "Get";
wrt2.Headers.Add("Host", "i.taobao.com");

wrt2.CookieContainer = Co1;
HttpWebResponse wrp2;
wrp2 = (HttpWebResponse)wrt2.GetResponse();
Co1.Add(wrp2.Cookies);

string htmlout2;
htmlout2 = new StreamReader(wrp2.GetResponseStream(), Encoding.GetEncoding("GB2312")).ReadToEnd();
richTextBox1.AppendText(htmlout2);
网址在ie里能跳转,我的程序里得到的却还是登陆的界面


 回复 引用   
#41楼 2009-11-08 18:50 威威[未注册用户]
希望你快点看到,帮帮我啊
 回复 引用 查看   
#42楼[楼主] 2009-11-08 21:09 深蓝      
@威威
不知道服务器抛出了什么错误啊?如果服务器没有跳转那也是无所谓的,只要认证通过了就可以用这个Cookie来发送请求了。

 回复 引用   
#43楼 2009-11-09 08:59 威威[未注册用户]
谢谢啊,我写网站登陆就是靠你这篇文章啊,文章阅读都达6000多了,

是这样的,我请求文中的地址,响应会得到一个302状态码,提示moved,还会发来多个set_cookie,我通过Location得到地址会是“http://i.taobao.com/my_taobao.htm?nekott=tq3B6cH61257726720557”之类的,与第一个地址比较"http://member1.taobao.com/member/login.jhtml?TPL_password=" + textBox2.Text(密码) + "&TPL_redirect_url=&TPL_username=" + HttpUtility.UrlEncode(textBox1.Text(用户名,汉字), Encoding.GetEncoding("GBK")) +"&_oooo_=&abtest=&action=Authenticator&actionForStable"

会发现子域名路径变了(不知道这样说对不对),直接用发来多个的set_cookie请求Location地址会提示让重新登陆,而在ie里会到达个人首页,我用wpe解包发现ie已经对set_cookie作了处理,具体如下





 回复 引用   
#44楼 2009-11-09 09:00 威威[未注册用户]
Set-Cookie x=162554239; Domain=taobao.com; Path=/,uc1=_yb_=false&_rt_=1229745254&_msg_=0&_msg_v=false&cookie21=VFC%2FuZ9ahQBYOA%3D%3D&cookie14=UoM%2BHZwYo%2FyqjA%3D%3D&cookie15=Vq8l%2BKCLz3%2F65A%3D%3D&cookie16=VT5L2FSpNgq6fDudInPRgavC%2BQ%3D%3D&existShop=true&existXShop=false&enabledWuiShop=false&lltime=1257725601; Domain=.taobao.com; Path=/,_sv_=1; Domain=.taobao.com; Path=/,dynamic_login=; Domain=member1.taobao.com; Expires=Tue, 09-Nov-2010 00:32:00 GMT; Path=/member/,tg=0; Domain=.taobao.com; Expires=Wed, 27-Jul-2011 00:32:00 GMT; Path=/,_cc_=VFC%2FuZ9ajQ%3D%3D; Domain=.taobao.com; Expires=Tue, 09-Nov-2010 00:32:00 GMT; Path=/,t=65ecba08ccd663a6e77d2c5fe9aa33c6; Domain=.taobao.com; Expires=Fri, 09-Aug-2019 01:12:00 GMT; Path=/,nt=W5iHLLyFKOn9Fm4pXdO58YyFZHjq0e4Jy9J9hpwCdg%3D%3D; Domain=.taobao.com; Expires=Tue, 09-Mar-2021 17:25:20 GMT; Path=/member,_nk_=%5Cu8463%5Cu7075%5Cu9F99; Domain=.taobao.com; Path=/,_ad_=; Domain=.taobao.com; Expires=Fri, 09-Aug-2019 01:12:00 GMT; Path=/,_l_g_=Ug%3D%3D; Domain=.taobao.com; Path=/,cookie2=d233d241fa5c2ae1274a21495fa9326c;Domain=.taobao.com;Path=/;httpOnly,_wwmsg_=0%2C0; Domain=.taobao.com; Path=/,tracknick=%5Cu8463%5Cu7075%5Cu9F99; Domain=.taobao.com; Expires=Tue, 09-Nov-2010 00:32:00 GMT; Path=/,ssllogin=; Domain=.taobao.com; Expires=Tue, 09-Nov-2010 00:32:00 GMT; Path=/,ssl_dynamic_login=; Domain=.taobao.com; Expires=Tue, 09-Nov-2010 00:32:00 GMT; Path=/member/,lastgetwwmsg=MTI1NzcyNjcyMA%3D%3D; Domain=.taobao.com; Path=/,cookie1=BYFRAHU3IqCz1Wcu%2Fdzz%2FN8WM3m0WZ01H5i48Qm9yzw%3D;Domain=.taobao.com;Path=/;httpOnly,cookie17=Uoe2yIbEKTgs;Domain=.taobao.com;Path=/;

我注意到ie发送cookie时dynamic_login=; Domain=member1.taobao.com;之类的
domain为member1.taobao.com的cookie都没有出现

我想这可能是失败原因,看了好多遍CookieContainer类,还是弄不请它与cookcollection,cookie之间的关系,我正在尝试手工处理cookie,看看能不能行
谢谢你的回复这么快

 回复 引用 查看   
#45楼 2010-11-06 17:56 jmccount      
想DOWN个附件 可是DOWN不下来 不知道怎么搞的
 回复 引用 查看   
#46楼 2011-07-21 14:48 誓丿小忒      
楼主能不能加下QQ 402163943 ,我有问题想请教你

我要啦免费统计