vc++使用cookie登录网站

以http://www.idc816.com为例

效果图:

1)先登录获取cookie,再使用cookie获取用户信息

 2)记录cookie,关闭程序后重新运行程序,直接获取用户信息

使用Fiddler抓包分析:

 由于IWinHttpRequest对象会自动处理302跳转,但是服务器返回的cookie(Set-Cookie)正好在响应头中,因此需要设置取消IWinHttpRequest的自动重定向功能

通过put_option函数进行设置WinHttpRequestOption_EnableRedirects项为VARIANT_FALSE

此外,默认情况下WinHttpRequest会自动将服务器返回的 Set-Cookie信息设置到当前WinHttpRequest对象的Header上面,下次当访问相同域的网址时会自动带上对应的Cookie

代码:

#import "C:\Windows\System32\winhttp.dll" no_namespace

#define GET_WINHTTP_RESPONSE_STRING(IWinHttpRequestPtr_Obj, CString_Obj) 
{
_variant_t varRspBody = IWinHttpRequestPtr_Obj->ResponseBody; 
char *pContentBuffer = (char*)varRspBody.parray->pvData; 
CString_Obj = pContentBuffer; 
}

CString Get_Recv_Cookie(const CString &respHeader)
{
    CString cookie;
    CString key = _T("Set-Cookie:");
    int iBegin = 0, iEnd = 0;
    while (iBegin < respHeader.GetLength())
    {
        iBegin = respHeader.Find(key, iBegin);
        if (iBegin >= 0) // 找到
        {
            iEnd = respHeader.Find(_T("
"), iBegin);
            if (iEnd >= 0)
            {
                cookie += respHeader.Mid(iBegin, iEnd - iBegin + 2); // 包括换行
                iBegin = iEnd; 
            }
        }
        else {
            break;
        }
    }
    return cookie;
}



// 登录
void CHttpLoginWithCookieTestDlg::OnBnClickedButtonLogin()
{
    // 获取用户名,密码
    CString username, passwd;
    GetDlgItemText(IDC_EDIT_NAME, username);
    GetDlgItemText(IDC_EDIT_PASSWD, passwd);
    if (username.IsEmpty() || passwd.IsEmpty())
    {
        MessageBox(_T("用户名或者密码为空"));
        return;
    }

    IWinHttpRequestPtr pHttpReq = NULL;
    HRESULT hr = pHttpReq.CreateInstance(__uuidof(WinHttpRequest));
    if (FAILED(hr))
        return;

    // 建立连接
    hr = pHttpReq->Open(_T("POST"), _T("http://www.idc816.com/chklogin.asp"));
    if (FAILED(hr))
        return;

    // post数据此项必须设置
    pHttpReq->SetRequestHeader(_T("Content-Type"), _T("application/x-www-form-urlencoded"));

    // 取消自动处理302重定向,是为了获取响应头中的Set-Cookie
    COleVariant varRedirect = VARIANT_FALSE;
    pHttpReq->put_Option(WinHttpRequestOption_EnableRedirects, varRedirect);
  // pHttpReq->Option[WinHttpRequestOption_EnableRedirects] = VARIANT_FALSE; CString body; body.Format(_T(
"u_name=%s&u_password=%s&imageField.x=29&imageField.y=9"), username, passwd); COleVariant varBody = body; hr = pHttpReq->Send(varBody); if (FAILED(hr)) return; CString respStr; GET_WINHTTP_RESPONSE_STRING(pHttpReq, respStr); long statusCode = pHttpReq->Status; if (statusCode == 302 && respStr.Find(_T("/Manager/")) != -1) { // 获取响应头 CString respHeader = pHttpReq->GetAllResponseHeaders(); // 获取cookie CString cookie = Get_Recv_Cookie(respHeader); // 显示cookie, 需要将输入框的Multiline属性设为True SetDlgItemText(IDC_EDIT_COOKIE_RECV, cookie); MessageBox(_T("登录成功")); } else { MessageBox(_T("登录失败")); } } // 获取信息 void CHttpLoginWithCookieTestDlg::OnBnClickedButtonInfo() { IWinHttpRequestPtr pHttpReq = NULL; HRESULT hr = pHttpReq.CreateInstance(__uuidof(WinHttpRequest)); if (FAILED(hr)) return; hr = pHttpReq->Open(_T("GET"), _T("http://www.idc816.com/manager/usermanager/default2.asp")); if (FAILED(hr)) return; // 从输入框中获取cookie CString cookie; GetDlgItemText(IDC_EDIT_COOKIE_SEND, cookie); // 设置cookie if (cookie.GetLength() > 0) pHttpReq->SetRequestHeader(_T("Cookie"), cookie.GetString()); hr = pHttpReq->Send(); if (FAILED(hr)) return; CString respStr; GET_WINHTTP_RESPONSE_STRING(pHttpReq, respStr); CString company, tel, qq; company = getMidStrByLeftAndRight(respStr, _T("name=u_company value=""), _T(""")); tel = getMidStrByLeftAndRight(respStr, _T("name=u_telphone value=""), _T(""")); qq = getMidStrByLeftAndRight(respStr, _T("name=qq value=""), _T(""")); SetDlgItemText(IDC_STATIC_COMPANY, company); SetDlgItemText(IDC_STATIC_TEL, tel); SetDlgItemText(IDC_STATIC_QQ, qq); } CString CHttpLoginWithCookieTestDlg::getMidStrByLeftAndRight(const CString &str, const CString &left, const CString &right) { CString ret; int posLeft = -1, posRight = -1; posLeft = str.Find(left); if (posLeft == -1) return ret; posLeft += left.GetLength(); // 所求字符串的起始位置 posRight = str.Find(right, posLeft); // 所求字符串的结束位置 if (posRight == -1) return ret; ret = str.Mid(posLeft, posRight - posLeft); return ret; }
原文地址:https://www.cnblogs.com/hupeng1234/p/6906566.html