這幾天課比較少,校園網上網要認證才能上網,每次必須輸入學號密碼,為了方便,寫了一個自動登錄以及如果在線,登錄自服務系統強制下線的小工具。
強制下線思路:獲取sessionID----------》獲取驗證碼圖片------------》AspriseOCRLib識別驗證碼---------------》MD5加密、url Encode----------------》登錄自服務系統----------------》強制下線---------------------》退出登錄。
需要注意的問題:
1、獲取驗證碼時,發送完請求應該Sleep 1秒,等待接收完畢,再調用recv讀緩沖區,否則可能圖片為接受完。
2、登錄請求后需要延時,等待服務器把登錄狀態set進session中,才可以進行操作。
3、每次發送請求需要使用不同的socket連接。
下面貼一部分代碼:(代碼有很多疏漏之處,歡迎指正,共同進步)
轉載請標明出處。
1、獲取連接
1 BOOL CforceOutLineDlg::ConnectToServer(const CString strServerUrl,SOCKET& socketClient, const unsigned short nPort) 2 { 3 BOOL bRet = FALSE; 4 WSADATA wsaData; 5 WORD wVersion = MAKEWORD(2,2); 6 7 do 8 { 9 if(0 != WSAStartup(wVersion, &wsaData)) 10 { 11 break; 12 } 13 14 if(LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) 15 { 16 WSACleanup(); 17 break; 18 } 19 20 LPHOSTENT lpHostTent; 21 lpHostTent = gethostbyname(strServerUrl);///根據url獲取ip 22 if (NULL == lpHostTent) 23 { 24 break; 25 } 26 27 28 if (socketClient == INVALID_SOCKET) 29 { 30 WSACleanup(); 31 break; 32 } 33 34 SOCKADDR_IN socketServer;//服務器 35 socketServer.sin_family = AF_INET; 36 socketServer.sin_port = htons(nPort); 37 socketServer.sin_addr = *((LPIN_ADDR)*lpHostTent->h_addr_list); 38 39 40 socketClient = socket(AF_INET, SOCK_STREAM, 0); 41 42 if (SOCKET_ERROR == connect(socketClient, (LPSOCKADDR)&socketServer, sizeof(SOCKADDR_IN))) 43 { 44 int nErrorCode = WSAGetLastError(); 45 closesocket(socketClient); 46 break; 47 } 48 49 bRet = TRUE; 50 } while (FALSE); 51 52 return bRet; 53 }
2、接收驗證碼
BOOL CforceOutLineDlg::GetValidateCode(/*SOCKET s,*/CString sessionid)
{
SOCKET client;
ConnectToServer("IP",client);//初始化連接
CString cstrSendData;
cstrSendData = "GET /RandomCodeAction.action?randomNum=0.1 HTTP/1.1\r\n";
cstrSendData += "Host: \r\n";
cstrSendData += "Connection: keep-alive\r\n";
cstrSendData += "Accept: image/webp,image/*,*/*;q=0.8\r\n";
cstrSendData += "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36\r\n";
cstrSendData += "Referer:\r\n";
cstrSendData += "Accept-Encoding: gzip, deflate, sdch\r\n";
cstrSendData += "Accept-Language: zh-CN,zh;q=0.8\r\n";
cstrSendData += "Cookie: JSESSIONID=" + sessionid + "\r\n";
cstrSendData += "\r\n";
if (-1 == send(client, cstrSendData.GetBuffer(), cstrSendData.GetLength(), 0))
{
return FALSE;
}
char buff[4096]={0};
Sleep(1000);//延時1秒,等待圖片流接收完畢
recv(client, buff, sizeof(buff),0);
CString temp = buff;
int nFirst = temp.Find("close",0);
if(nFirst == -1)
return FALSE;
nFirst += 9;//加上close 兩個\r\n 一個 0 的長度
int picLength = GetPicLength(buff+nFirst);
ofstream out("aa.png",ios::out|ios::binary);
out.write(buff+nFirst,picLength);
out.flush();
out.close();
closesocket(client);
return TRUE;
}
int CforceOutLineDlg::GetPicLength(char* pic)//查找到連續5個 0x00 的位置
{
int count = 0,i;
for(i = 0;;i++)
{
if(pic[i]==0)
{
count++;
if(count==5)
{
break;
}
}
else
{
count = 0;
}
}
return i-4;
}
3、URlEncode
CString CforceOutLineDlg::UrlEncode(const CString& szToEncode)
{
std::string src = szToEncode;
char hex[] = "0123456789ABCDEF";
CString dst;
for (size_t i = 0; i < src.size(); ++i)
{
unsigned char cc = src[i];
if(cc == '\\')
continue;
if ( cc >= 'A' && cc <= 'Z'
|| cc >='a' && cc <= 'z'
|| cc >='0' && cc <= '9'
|| cc == '.'
|| cc == '_'
|| cc == '-'
|| cc == '*'
)
{
if (cc == ' ')
{
dst += "+";
}
else
dst += cc;
}
else
{
unsigned char c = static_cast<unsigned char>(src[i]);
dst += '%';
dst += hex[c / 16];
dst += hex[c % 16];
}
}
return dst;
}
轉載請標明出處。
