Vba 不理解为什么WinHTTP不验证某些HTTPS资源

Vba 不理解为什么WinHTTP不验证某些HTTPS资源,vba,authentication,https,winhttp,Vba,Authentication,Https,Winhttp,我非常感谢任何能帮助我解决问题的帮助 从Excel VBA代码中,我需要从HTTPS站点下载并解析CSV文件。我尝试使用WinHTTP获取文件。然而,我不明白为什么身份验证不起作用。以下是一段相关代码: TargetURL = "https://redmine.itransition.com/projects/pmct/time_entries.csv" Set HTTPReq = CreateObject("WinHttp.WinHttpRequest.5.1") HTTPReq.Option

我非常感谢任何能帮助我解决问题的帮助

从Excel VBA代码中,我需要从HTTPS站点下载并解析CSV文件。我尝试使用WinHTTP获取文件。然而,我不明白为什么身份验证不起作用。以下是一段相关代码:

TargetURL = "https://redmine.itransition.com/projects/pmct/time_entries.csv"
Set HTTPReq = CreateObject("WinHttp.WinHttpRequest.5.1")
HTTPReq.Option(4) = 13056 ' WinHttpRequestOption_SslErrorIgnoreFlags 13056: ignore all err, 0: accept no err
HTTPReq.Open "GET", TargetURL, False
HTTPReq.SetCredentials "UN", "PW", 0
HTTPReq.send
返回以下响应(仅列出某些字符串):

但是,如果我在使用成功的手动身份验证之后从Firefox Cookie发送“Cookie”字符串

HTTPReq.setRequestHeader "Cookie", SetCookieString
HTTPReq.send
我很容易得到预期的文件。当然,我对这种解决方案不满意,希望执行真正的WinHTTP身份验证。然而,我无法理解代码中有什么错误或遗漏了什么。很可能我必须使用
.SetClientCertificate
方法,但我不清楚这是需要哪个证书

或者,更一般地说:我应该使用哪些WinHTTP方法或函数进行调试,以找出哪个步骤是阻塞/不正确的,并阻止我进行正确的身份验证?我花了两周时间通过MSDN和各种资源进行搜索,但仍然没有解决方案

提前感谢您的建议

上的登录只是一个HTML表单,它将用户名和密码发布到
/login
上的脚本中

这与专为基于服务器的身份验证方案(如basic/digest/ntlm)设计的
SetCredentials
不兼容

您需要在没有凭据的情况下加载该页面,从生成的表单中获取类似于volatile字段的内容
authenticity\u token
,并将其与用户名和密码一起发布到
/login


如果它是基于会话的系统,它将使用设置好的cookie头+数据进行响应,您需要在后续请求中使用这些数据。

上面的@Alex K。响应正是我一直在寻找的! 在Firebug和MSDN的帮助下,我完成了3个请求:

  • 获取使用RegEx从登录页面收集真实性令牌数据的请求
  • POST请求进行身份验证并从响应中收集所需的Cookie字符串
  • 获取请求以最终获得我心爱的CSV
以下代码按预期工作:

Set RegX_AuthToken = CreateObject("VBScript.RegExp")
' Below Pattern w/o double-quotes encoded: (?:input name="authenticity_token" type="hidden" value=")(.*)(?:")
RegX_AuthToken.Pattern = "(?:input name=" & Chr(34) & "authenticity_token" & Chr(34) & " type=" & Chr(34) & "hidden" & Chr(34) & " value=" & Chr(34) & ")(.*)(?:" & Chr(34) & ")"
RegX_AuthToken.IgnoreCase = True
RegX_AuthToken.Global = True

TargetURL = "https://redmine.itransition.com/login"

Set HTTPReq = CreateObject("WinHttp.WinHttpRequest.5.1")
HTTPReq.Open "GET", TargetURL, False
HTTPReq.Send

Set Token_Match = RegX_AuthToken.Execute(HTTPReq.ResponseText)
AuthToken = Token_Match.Item(0).SubMatches.Item(0)

PostData = "authenticity_token=" & AuthToken & "&back_url=https://redmine.itransition.com/" & "&username=" & UN & "&password=" & PW & "&login=Login »"

HTTPReq.Open "POST", TargetURL, False
HTTPReq.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
HTTPReq.Send (PostData)

SetCookieString = HTTPReq.GetResponseHeader("Set-Cookie")

TargetURL = "https://redmine.itransition.com/projects/pmct/time_entries.csv"
HTTPReq.Open "GET", TargetURL, False
HTTPReq.setRequestHeader "Cookie", SetCookieString
HTTPReq.Send
以下URL有助于生成POST请求:

你需要在没有凭据的情况下加载该页面,然后抓取看起来像什么 来自生成表单和post的volatile字段标记 以及登录/登录的用户名和密码

亚历克斯K-再次感谢你的精彩建议!(:

还有一件事(除上述解决方案外)如果使用类似于上述代码的POST请求,您应该注意:出于某种模糊的原因,我仍然有4-5次收到一次(甚至更多)该网站令人讨厌的406响应,这意味着在我的情况下,auth不完整。经过数小时的逐步调试,我高兴地发现了原因:auth令牌值可能有
+
符号,通过分析几十个auth令牌/响应代码的箭头,我发现
+
-包含令牌精确匹配406个代码

解决方案变得非常明显:为
PostData
安全地URL编码
+
es。在我的帮助下,我最终得出以下结论:

PostData = "authenticity_token=" & Replace(AuthToken, "+", "%2B", vbTextCompare) & _
    "&back_url=https://redmine.itransition.com/projects/" & Trim(RedmineProject) & _
    "/time_entries" & "&username=" & UN & "&password=" & PW & "&login=Login »"
+
es被
%2B
s取代,这就是-不再是406s了!)


其他特殊的字符在我的情况下并不重要,但教训是吸取的。希望这能为其他人节省几个小时的生命

也许这会有所帮助:我需要对Redmine实例进行身份验证(更多信息,请参阅)。406HTTP状态码与身份验证无关-如果需要身份验证,您应该获得401或407代码。406是-“406不可接受:根据请求中发送的accept标头,请求标识的资源只能生成具有不可接受内容特征的响应实体”-请参阅@barrowc感谢您的重点介绍!事实上,406和auth根本没有关系——在我的上下文中,它意味着我收到的响应与200/OK不同,这是我在使用浏览器中的cookie字符串时得到的响应。和一个以上的X为有用的链接!谢谢你的建议-我的最终工作代码如下!我知道这是一篇老文章,但需要你的帮助从一个安全的网站下载图像。我有我的登录用户名和密码,并尝试了各种方式下载它。我可以在登录后手动下载图像,例如,但不知道如何使用您在Authentity_token上共享的示例下载图像。如何为其编写正则表达式并找到其真实性标记?仅供参考,3520198是图像的名称。您是如何分别找到正确的
PostData
AuthToken.Pattern
?我试图从一个安全的站点下载文档,但它没有暴露URL字符串中的任何内容。当我想要下载时,我得到的所有信息都是+
授权令牌丢失
。我将登录页面的
ResponseText
GetAllResponseHeaders()
放在上面。我找不到任何与授权令牌相关的内容。
PostData = "authenticity_token=" & Replace(AuthToken, "+", "%2B", vbTextCompare) & _
    "&back_url=https://redmine.itransition.com/projects/" & Trim(RedmineProject) & _
    "/time_entries" & "&username=" & UN & "&password=" & PW & "&login=Login »"