POST教程笔记 - POST方式登录网站

www.cctry.com post教程

注意,本文章并非教程

//http://www.idc3389.com/user/modify.asp 源码
// 中找用户数据
CString findUserinfo(CString strElemet,CString strHtmlSrc)
{
    if (strElemet == L"" || strHtmlSrc == L""){
        return NULL;
    }

    int pos = strHtmlSrc.Find(strElemet);
    if (pos == -1)
    {
        return NULL;
    }
    pos = pos + strElemet.GetLength() + 8; // _value="
    UINT len = strHtmlSrc.GetLength();
    strHtmlSrc = strHtmlSrc.Right(len - pos);
    pos = strHtmlSrc.Find(L"\"");
    strHtmlSrc = strHtmlSrc.Left(pos);
    //AfxMessageBox(strHtmlSrc);

    return strHtmlSrc;
}

 

抓取到的封包

//以下为请求头:
POST http://www.idc3389.com/user/userlogin.asp HTTP/1.1
Host: www.idc3389.com
Connection: keep-alive
Content-Length: 83
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://www.idc3389.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 BIDUBrowser/6.x Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://www.idc3389.com/
Accept-Encoding: gzip,deflate
Accept-Language: zh-CN,zh;q=0.8
Cookie: pgv_pvid=9485415913; pgv_pvi=1262146560; ASPSESSIONIDAQCTDDQD=NBANEFEBEOFJHGFBANHADDKO; __qc_wId=959; IESESSION=alive; pgv_si=s8099517440

username=username&password=password&screenwidth=&screenheight=&Submit.x=29&Submit.y=12


//以下为应答头:
HTTP/1.1 302 Object moved
Date: Sun, 12 Oct 2014 14:10:22 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Location: logininfo.asp
Content-Length: 134
Content-Type: text/html
Cache-control: private

<head><title>Object moved</title></head>
<body><h1>Object Moved</h1>This object may be found <a HREF="logininfo.asp">here</a>.</body>

 

 

主要代码如下,做了简单注释

 

/*
    HTTP1.1协议规定的 HTTP 请求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 这几种。
    其中 POST 一般用来向服务端提交数据,本文主要讨论 POST 提交数据的几种方式。
    我们知道,HTTP 协议是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范。
    规范把 HTTP 请求分为三个部分:状态行、请求头、消息主体。


    协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。
    实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。
    但是,数据发送出去,还要服务端解析成功才有意义。一般服务端语言如 php、python 等,以及它们的 framework,
    都内置了自动解析常见数据格式的功能。
    服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,
    再对主体进行解析。所以说到 POST 提交数据方案,包含了 Content-Type 和消息主体编码方式两部分。

*/

#import "C:\\Windows\\syswow64\\winhttp.dll" no_namespace
void Cidc3389LoginDlg::OnBnClickedButton1()
{
    CString strUserName, strPassword;
    GetDlgItemText(IDC_EDIT1, strUserName);
    GetDlgItemText(IDC_EDIT2, strPassword);
    if (strUserName == L"" || L"" == strPassword){
        MessageBox(L"账号或密码不能为空");
        return;
    }

    CoInitialize(NULL);
    IWinHttpRequestPtr pHttpReq = NULL;
    HRESULT hr = pHttpReq.CreateInstance(__uuidof(WinHttpRequest));
    if (FAILED(hr)){
        CoUninitialize();
    }

    hr = pHttpReq->Open(L"POST", L"http://www.idc3389.com/user/userlogin.asp");
    if (FAILED(hr)){
        CoUninitialize();
    }

    // 这里注意设置content-type
    // Content-Type: application/x-www-form-urlencoded
    pHttpReq->SetRequestHeader(L"Content-Type", L"application/x-www-form-urlencoded");

    // 发送POST请求
    CString strPost;
    strPost.Format(
        L"username=%s&password=%s&screenwidth=&screenheight=&Submit.x=38&Submit.y=14",
        strUserName,
        strPassword
        );

    variant_t varPost;
    varPost = strPost;
    hr = pHttpReq->Send(varPost);
    if (FAILED(hr)) {
        CoUninitialize();
    }
    
//     // 通过状态码判断登录是否成功;
//  long status = -1;
//     pHttpReq->get_Status(&status);
//     if (status != 200){
//         MessageBox(L"登录失败!请检查用户名和密码是否有误!");
//         goto _exit0;
//     }

    // syc老大的方法, 获取网页元素,判断是否有"欢迎您",这是针对该网站网页源码的。
    // 不同网站不同对待
    _variant_t varRspBody = pHttpReq->GetResponseBody();
    ULONG dataLen = varRspBody.parray->rgsabound[0].cElements;
    char *pContentBuffer = (char *)varRspBody.parray->pvData;
    CString strCntBuffer;
    strCntBuffer = pContentBuffer;

    CString strSucKey(_T("欢迎您:"));
    if (strCntBuffer.Find(strSucKey) != -1){
        GetDlgItem(IDC_EDIT1)->EnableWindow(FALSE);
        GetDlgItem(IDC_EDIT2)->EnableWindow(FALSE);

        MessageBox(_T("登陆成功!"));
    }
    else {
        MessageBox(_T("登陆失败!"));
    }


    // 登录成功后获取用户信息
    hr = pHttpReq->Open(L"GET", L"http://www.idc3389.com/user/modify.asp");
    if (FAILED(hr)) {
        CoUninitialize();
    }
    hr = pHttpReq->Send();
    if (FAILED(hr)) {
        CoUninitialize();
    }

    // 解决乱码问题
    varRspBody = pHttpReq->GetResponseBody();
    dataLen = varRspBody.parray->rgsabound[0].cElements;
    pContentBuffer = (char *)varRspBody.parray->pvData;
    CString strHtmlSrc;
    strHtmlSrc = pContentBuffer;

    // 姓名、身份证、EMAIL、TEL

    CString strElement = L"id=\"truename\"";
    CString strUserInfo = findUserinfo(strElement, strHtmlSrc);
    GetDlgItem(EDIT_TRUENAME)->SetWindowTextW(strUserInfo);

    strElement = L"id=\"address\"";
    strUserInfo = findUserinfo(strElement, strHtmlSrc);
    GetDlgItem(EDIT_ADDRESS)->SetWindowTextW(strUserInfo);

    strElement = L"id=\"mobi\"";
    strUserInfo = findUserinfo(strElement, strHtmlSrc);
    GetDlgItem(EDIT_TEL)->SetWindowTextW(strUserInfo);

    strElement = L"id=\"email\"";
    strUserInfo = findUserinfo(strElement, strHtmlSrc);
    GetDlgItem(EDIT_E_MAIL)->SetWindowTextW(strUserInfo);

    CoUninitialize(); // 关闭的时候再卸载COM组件
}

 

posted @ 2015-11-03 20:31  Lthis  阅读(1843)  评论(0编辑  收藏  举报