Vba 使用Cookie身份验证和CSRF令牌连接到Web API
*最后更新 我需要使用API进行身份验证的帮助。 我正在使用VBA和Power Query从我的Garmin帐户自动收集训练数据。据我所知,该网站使用基于cookie的身份验证和CSRF令牌 我正在Postman中测试API调用,在VBA中构建身份验证请求,并使用经过身份验证的cookie在Power Query中执行数据收集。(我会对整个项目使用powerquery,但它无法返回响应头/经过验证的cookie) 在发出身份验证POST请求之前,我试图通过从响应头收集cookie和从HTML主体收集CSRF令牌来复制浏览器操作,但我没有取得多大成功。当我尝试使用此方法进行身份验证时,响应状态为200,响应主体是带有“出错”消息的登录页面 我试着按照这个问题的答案来处理饼干, 在Postman或VBAVba 使用Cookie身份验证和CSRF令牌连接到Web API,vba,session-cookies,csrf,msxml,api-authorization,Vba,Session Cookies,Csrf,Msxml,Api Authorization,*最后更新 我需要使用API进行身份验证的帮助。 我正在使用VBA和Power Query从我的Garmin帐户自动收集训练数据。据我所知,该网站使用基于cookie的身份验证和CSRF令牌 我正在Postman中测试API调用,在VBA中构建身份验证请求,并使用经过身份验证的cookie在Power Query中执行数据收集。(我会对整个项目使用powerquery,但它无法返回响应头/经过验证的cookie) 在发出身份验证POST请求之前,我试图通过从响应头收集cookie和从HTML主体
MSXML2.ServerXMLHTTP
中是否有处理CSRF令牌的特殊方法?关于cookie身份验证,是否有一些我根本不了解的地方
如果你需要我提供更多的信息,请告诉我。非常感谢您的帮助
我的代码修改版本如下:
Option Explicit
Sub GetCookie()
Dim sUrl, sRespHeaders, sRespText, aSetHeaders, aList, aSetBody, sCSRFToken, sBody
sBody = "username=USERNAME&password=PASSWORD&embed=false&_csrf="
' get cookie 1
sUrl = "https://connect.garmin.com/signin/"
XmlHttpRequest "GET", sUrl, Array(), "", sRespHeaders, sRespText
ParseResponse "^Set-(Cookie): (\S*?=\S*?);[\s\S]*?$", sRespHeaders, aSetHeaders
' get cookie 2 and CSRF Token
sUrl = "https://sso.garmin.com/sso/signin?service=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&webhost=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&source=https%3A%2F%2Fconnect.garmin.com%2Fsignin%2F&redirectAfterAccountLoginUrl=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&redirectAfterAccountCreationUrl=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso&locale=en_US&id=gauth-widget&cssUrl=https%3A%2F%2Fconnect.garmin.com%2Fgauth-custom-v1.2-min.css&privacyStatementUrl=https%3A%2F%2Fwww.garmin.com%2Fen-US%2Fprivacy%2Fconnect%2F&clientId=GarminConnect&displayNameShown=false&consumeServiceTicket=false&generateExtraServiceTicket=true&generateTwoExtraServiceTickets=false&generateNoServiceTicket=false&globalOptInShown=true&globalOptInChecked=false&connectLegalTerms=true&locationPromptShown=true&showPassword=true"
XmlHttpRequest "GET", sUrl, aSetHeaders, "", sRespHeaders, sRespText
' parse project names
ParseResponse "^Set-(Cookie): (\S*?=\S*?);[\s\S]*?$", sRespHeaders, aSetHeaders
sCSRFToken = GetCSRFToken("name=" & Chr(34) & "_csrf" & Chr(34) & " value=" & Chr(34), sRespText)
' get authenticated cookies
sUrl = "https://sso.garmin.com/sso/signin?service=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&webhost=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&source=https%3A%2F%2Fconnect.garmin.com%2Fsignin%2F&redirectAfterAccountLoginUrl=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&redirectAfterAccountCreationUrl=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso&locale=en_US&id=gauth-widget&cssUrl=https%3A%2F%2Fconnect.garmin.com%2Fgauth-custom-v1.2-min.css&privacyStatementUrl=https%3A%2F%2Fwww.garmin.com%2Fen-US%2Fprivacy%2Fconnect%2F&clientId=GarminConnect&displayNameShown=false&consumeServiceTicket=false&generateExtraServiceTicket=true&generateTwoExtraServiceTickets=false&generateNoServiceTicket=false&globalOptInShown=true&globalOptInChecked=false&connectLegalTerms=true&locationPromptShown=true&showPassword=true"
XmlHttpRequest "POST", sUrl, aSetHeaders, sBody & sCSRFToken, sRespHeaders, sRespText
' parse project names
ParseResponse "^Set-(Cookie): (\S*?=\S*?);[\s\S]*?$", sRespHeaders, aSetHeaders
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
If IsEmpty(aData) Then
aData = Array()
End If
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
Function GetCSRFToken(sPattern, sResponse)
Dim lStart, lLength, sSubMatch
lStart = InStr(1, sResponse, sPattern) + Len(sPattern)
lLength = InStr(lStart, sResponse, Chr(34)) - lStart
GetCSRFToken = Mid(sResponse, lStart, lLength)
End Function
Sub PushItem(aList, vItem)
ReDim Preserve aList(UBound(aList) + 1)
aList(UBound(aList)) = vItem
End Sub
编辑 我改变了创建InternetExplorer实例的方法,并自动化了登录过程。不理想,但我能够成功登录。我现在的问题是,我无法检索维护登录会话所需的HttpOnly Cookie
getCookie=objIE.document.Cookie
我尝试了另一个答案(巧合),但没有成功
如果您对如何使用MSXML2.ServerXMLHTTP、IE实例或任何其他方法实现此功能有任何建议,我们将不胜感激 尝试在禁用重定向的情况下发出请求以检索令牌和Cookie,如。感谢您的建议@omegastripes,我将试一试。@omegastripes禁用重定向似乎不起作用。我开始认为问题可能是每个请求都在重新计算csrf令牌。可能吗?有没有一种方法可以保持打开的连接以模拟使用MSXML调用的浏览器?您可以在“网络”选项卡上的“浏览器开发人员工具”中看到,网站没有使用“保持活动”,并且令牌没有更改。检查那里的请求时,我还注意到还有一些其他的请求被记录下来,VBA代码中缺少这些请求可能会影响登录过程。