Tam*_*viv 5 cookies vba web-services jsessionid session-cookies
我在Excel 2010中使用MSXML2.XMLHTTP60为Tomcat 8.5.5上托管的Java REST Web服务编写VBA Web服务客户端.
在VBA中,我希望能够JSESSIONID=E4E7666024C56427645D65BEB49ADC11从响应中获取字符串,并能够在后续请求中设置它.(想要这样做的原因是,如果Excel崩溃,似乎这个cookie丢失了,用户必须再次进行身份验证.我希望能够为用户设置最后存储的会话ID,所以如果会话是在服务器上仍然存在,它们不必在Excel客户端中重新进行身份验证.)
我看到了一些在线资源,根据这些资源,下面将拉出JSESSIONID cookie,但最后一行总是打印出来:
Dim httpObj As New MSXML2.XMLHTTP60
With httpObj
    .Open "POST", URL, False
    .SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
    .SetRequestHeader "Connection", "keep-alive"
    .Send
End With
Debug.Print "Response header Cookie: " & httpObj.GetResponseHeader("Cookie")  'This should pull the JSESSIONID cookie but is empty
Run Code Online (Sandbox Code Playgroud)
当我打印时,httpObj.GetAllResponseHeaders我看不到任何包含JSESSIONID的标题.
在相同的资源中,以下应该设置所需的cookie,但它不会(我打印出服务器上传入请求的标题,并看到我的尝试没有覆盖JSESSIONID值).
httpObj.SetRequestHeader "Cookie", "JSESSIONID=blahblah"
Run Code Online (Sandbox Code Playgroud)
我可能会错过JSESSIONED如何传输的机制,以及VBA如何以及何时提取它并设置它.
如何才能做到这一点?我很欣赏任何正确方向的指针.
尝试使用MSXML2.ServerXMLHTTP来控制cookie.下面的代码显示了如何检索和解析cookie,以及如何使用该cookie发出请求:
Option Explicit
Sub Test_ehawaii_gov()
    Dim sUrl, sRespHeaders, sRespText, aSetHeaders, aList
    ' example for https://energy.ehawaii.gov/epd/public/energy-projects-map.html
    ' get cookies
    sUrl = "https://energy.ehawaii.gov/epd/public/energy-projects-map.html"
    XmlHttpRequest "GET", sUrl, Array(), "", sRespHeaders, sRespText
    ParseResponse "^Set-(Cookie): (\S*?=\S*?);[\s\S]*?$", sRespHeaders, aSetHeaders
    ' get projects list
    sUrl = "https://energy.ehawaii.gov/epd/public/energy-projects-list.json?sEcho=2&iColumns=5&sColumns=&iDisplayStart=1&iDisplayLength=0&mDataProp_0=0&mDataProp_1=1&mDataProp_2=2&mDataProp_3=3&mDataProp_4=4&sSearch=&bRegex=false&sSearch_0=&bRegex_0=false&bSearchable_0=true&sSearch_1=&bRegex_1=false&bSearchable_1=true&sSearch_2=&bRegex_2=false&bSearchable_2=true&sSearch_3=&bRegex_3=false&bSearchable_3=true&sSearch_4=&bRegex_4=false&bSearchable_4=true&iSortCol_0=0&sSortDir_0=asc&iSortingCols=1&bSortable_0=true&bSortable_1=true&bSortable_2=true&bSortable_3=true&bSortable_4=true"
    XmlHttpRequest "GET", sUrl, aSetHeaders, "", "", sRespText
    ' parse project names
    ParseResponse "\[""([\s\S]*?)""", sRespText, aList
    Debug.Print Join(aList, vbCrLf)
End Sub
Sub XmlHttpRequest(sMethod, sUrl, aSetHeaders, sPayload, sRespHeaders, sRespText)
    Dim aHeader
    With CreateObject("MSXML2.ServerXMLHTTP")
        .SetOption 2, 13056 ' SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS
        .Open sMethod, sUrl, False
        For Each aHeader In aSetHeaders
            .SetRequestHeader aHeader(0), aHeader(1)
        Next
        .Send (sPayload)
        sRespHeaders = .GetAllResponseHeaders
        sRespText = .ResponseText
    End With
End Sub
Sub ParseResponse(sPattern, sResponse, aData)
    Dim oMatch, aTmp, sSubMatch
    aData = Array()
    With CreateObject("VBScript.RegExp")
        .Global = True
        .MultiLine = True
        .Pattern = sPattern
        For Each oMatch In .Execute(sResponse)
            If oMatch.SubMatches.Count = 1 Then
                PushItem aData, oMatch.SubMatches(0)
            Else
                aTmp = Array()
                For Each sSubMatch In oMatch.SubMatches
                    PushItem aTmp, sSubMatch
                Next
                PushItem aData, aTmp
            End If
        Next
    End With
End Sub
Sub PushItem(aList, vItem)
    ReDim Preserve aList(UBound(aList) + 1)
    aList(UBound(aList)) = vItem
End Sub
Run Code Online (Sandbox Code Playgroud)
您可以在断点的Locals窗口中看到cookie解析的结果,第一个元素包含嵌套数组,表示JSESSIONID:
通常,上面的示例从http://energy.ehawaii.gov/epd/public/energy-projects-list.html(问题)中删除项目名称:
另一个例子是https://netforum.avectra.com/eweb/(问题).只需添加以下Sub:
Sub Test_avectra_com()
    Dim sUrl, sRespHeaders, sRespText, aSetHeaders
    ' example for https://netforum.avectra.com/eweb/
    sUrl = "https://netforum.avectra.com/eweb/DynamicPage.aspx?Site=NEFAR&WebCode=IndResult&FromSearchControl=Yes"
    XmlHttpRequest "GET", sUrl, Array(), "", sRespHeaders, sRespText
    ParseResponse "^Set-(Cookie): (\S*?=\S*?);[\s\S]*?$", sRespHeaders, aSetHeaders
End Sub
Run Code Online (Sandbox Code Playgroud)
您还可以在"本地"窗口中看到Cookie,不是JSESSIONID,而是显示方法的其他Cookie:
注意它是简化的方法,它解析所有cookie,无论路径,域,安全或HttpOnly选项.
虽然 omegastripes 发布了一个很好的解决方案,但我想分享我最终使用的解决方案。
我使用的原始 MSXML2.XMLHTTP60 对象不支持 cookie。所以我改用WinHttp.WinHttpRequest.
这需要添加对您的代码的引用:在 VBA IDE 中,转到工具--> 引用并确保Microsoft WinHTPP.Services version xxx选中该引用。
获取 cookie 并存储它的代码(假设一个httpObj类型为 的对象WinHttp.WinHttpRequest):
' Get the JESSIONID cookie
Dim strCookie As String
Dim jsessionidCookie As String
strCookie = httpObj.GetResponseHeader("Set-Cookie")     ' --> "JSESSIONID=40DD2DFCAF24A2D64544F55194FCE04E;path=/pamsservices;HttpOnly"
jsessionidCookie = GetJsessionIdCookie(strCookie)       ' Strips to  "JSESSIONID=40DD2DFCAF24A2D64544F55194FCE04E"
'Store JSESSIONID cookie in the cache sheet
Run Code Online (Sandbox Code Playgroud)
过程 GetJsessionIdCookie 在哪里:
' Takes a string of the form "JSESSIONID=40DD2DFCAF24A2D64544F55194FCE04E;path=/pamsservices;HttpOnly"
' and returns only the portion "JSESSIONID=40DD2DFCAF24A2D64544F55194FCE04E"
Public Function GetJsessionIdCookie(setCookieStr As String) As String
    'JSESSIONID=40DD2DFCAF24A2D64544F55194FCE04E;path=/pamsservices;HttpOnly
    Dim jsessionidCookie As String
    Dim words() As String
    Dim word As Variant
    words = Split(setCookieStr, ";")
    For Each word In words
        If InStr(1, word, "JSESSIONID") > 0 Then
            jsessionidCookie = word
        End If
    Next word
    GetJsessionIdCookie = jsessionidCookie
End Function
Run Code Online (Sandbox Code Playgroud)
这是创建 WinHttp.WinHttpRequest 对象并设置先前存储的 cookie 的方法:
Public Function GetHttpObj(httpMethod As String, uri As String, Optional async As Boolean = False, _
    Optional setJessionId As Boolean = True, _
    Optional contentType As String = "application/xml") As WinHttp.WinHttpRequest
    Dim cacheUtils As New CCacheUtils
    Dim httpObj As New WinHttp.WinHttpRequest
    With httpObj
        .Open httpMethod, uri, async
        .SetRequestHeader "origin", "pamsXL"
        .SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
        .SetRequestHeader "Connection", "keep-alive"
        .SetRequestHeader "Content-type", contentType
        .SetRequestHeader "cache-control", "no-cache"
    End With
    ' --- Pull stored cookie and attach to request ---
    If setJessionId Then
        httpObj.SetRequestHeader "Cookie", cacheUtils.GetCachedValue(wsJsessionidAddr)
    End If
    Set GetHttpObj = httpObj
End Function
Run Code Online (Sandbox Code Playgroud)
CCacheUtils我为存储和检索缓存值(例如 JSESSIONID cookie)而实现的类在哪里。
要动态获取和设置 cookie,我最近发现了一种最简单的方法。实施方式如下:
Sub GetRequestHeaders()
    Const URL$ = "https://finance.yahoo.com/quote/AAPL?p=AAPL"
    Dim Http As New ServerXMLHTTP60, Html As New HTMLDocument, strCookie$
    With Http
        .Open "GET", URL, False
        .send
        strCookie = .getAllResponseHeaders
        strCookie = Split(Split(strCookie, "Cookie:")(1), ";")(0)
        .Open "GET", URL, False
        .setRequestHeader "Cookie", Trim(strCookie)
        .send
        Html.body.innerHTML = .responseText
    End With
    MsgBox Html.querySelector("#quote-market-notice span").innerText
End Sub
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           11910 次  |  
        
|   最近记录:  |