使用vbscript / java在NTLM身份验证后自动下载动态生成的文件

时间:2013-06-14 04:31:30

标签: java excel-vba vbscript ntlm browser-automation

我正在尝试自动下载服务器上动态生成的文件,因此以下是我必须手动执行的步骤 -

  1. 使用我的凭据登录该站点 - 它使用NTLM进行身份验证。
  2. 登录后填写表单中的详细信息,使用post方法将详细信息发送到服务器并在服务器上生成文件并将响应恢复为服务器。
  3. 所以首先我想用VBScript做这件事:

    • 获取IE Automation对象

    • sendkeys发送用户名/密码

    • 导航到该页面并下载文件

    • Sendkeys切换到保存按钮 - 但在这里我卡住了因为IE提示我保存位置,我无法确定。另外我想打开它但是我无法以这种方式打开Excel文件的自动化对象:(

    即使wget也无法正常工作,因为我必须发布一些数据以及它将为我提供生成的Excel文件的基础。

    所以在网上搜索之后我发现我可以使用MSXML2.xmlhttp对象或Java套接字来完成它并使用get方法下载页面,但我必须再次提供我的凭据来打开页面。

    任何人都可以帮助我如何验证用户并以任何方式下载文件。

    编辑代码

    - 下载页面

    objmsXML.Open "GET", url, False
    objmsXML.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    objmsXML.setRequestHeader "Referer", url
    objmsXML.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36"
    objmsXML.send
    

    - 填写详细信息并发布数据

    If objmsXML.Status = 200 Then
      'First Response received.
      'get all the response headers
      responseHeaders = objmsXML.getAllResponseHeaders()
      responseBody = objmsXML.responseText    
    End If
    
    Dim viewState As String
    Dim eventTarget, eventArgument, txtProjectID, btnSubmit, grdReportPostDataValue
    Dim eventValidation As String
    
    viewState = Split(Split(responseBody, "__VIEWSTATE")(2), """")(2)
    viewState = URLEncode(viewState, False)
    
    eventTarget = ""
    eventArgument = ""
    txtProjectID = projectID
    btnSubmit = URLEncode("Submit")
    grdReportPostDataValue = ""
    eventValidation = Split(Split(responseBody, "__EVENTVALIDATION")(2), """")(2)
    eventValidation = URLEncode(eventValidation, False)
    
    objmsXML.Open "POST", url, False
    
    Dim postData
    postData = "__EVENTTARGET=" & eventTarget & "&__EVENTARGUMENT=" _
      & eventArgument & "&__VIEWSTATE=" & viewState & "&txtProjectID=" _
      & txtProjectID & "&btnSubmit=" & btnSubmit & "&grdReportPostDataValue" _
      & grdReportPostDataValue & "&__EVENTVALIDATION=" & eventValidation
    
    objmsXML.send postData
    

    但问题是,由于表格发布,它没有给我第二页。我相信这可能是因为我无法跟踪会话cookie。请帮忙。

1 个答案:

答案 0 :(得分:0)

您无法在未提供凭据的情况下对用户进行身份验证。在使用Fiddler之类的内容检查会话时手动下载文件一次。这将显示POST请求所需的标头。然后像这样自动化请求:

url = "http://..."

user = "..."
pass = "..."
credentials = "username=" & user & "&password=" & pass

Set req = CreateObject("Msxml2.XMLHttp.6.0")
req.open "POST", url, False
req.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
req.send credentials

根据Fiddler透露的内容修改credentials。您可能需要使用以下内容对上述示例中的值(userpass进行编码):

Function Encode(ByVal str)
  Set re = New RegExp
  re.Pattern = "[^a-zA-Z0-9_.~-]"

  enc = ""
  For i = 1 To Len(str)
    c = Mid(str, i, 1)
    If re.Test(c) Then c = "%" & Right("0" & Hex(Asc(c)), 2)
    enc = enc & c
  Next

  Encode = enc
End Function

responseBody保存到这样的文件中:

filename = "C:\your\output.xls"

Set stream = CreateObject("ADODB.Stream")

If req.status = 200 Then
  stream.Open
  stream.Type = 1 'binary
  stream.Write req.responseBody
  stream.SaveToFile filename, 2
  stream.Close
End If

如果文件名是动态生成的,您可能需要阅读响应和/或状态文本,并发送第二个请求以实际检索文件。但是,这取决于实际的服务器响应(由Fiddler透露)。

修改:我找到的解决方案here建议使用WinHttpRequest对象:

Set req = CreateObject("WinHttp.WinHttpRequest.5.1")
req.SetAutoLogonPolicy 0

req.Open "POST", url, False
req.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
req.Send credentials

我无法测试这个,因为我手边没有使用NTLM身份验证的Web服务器。