4

PowerShell 6.2.1 不使用 Invoke-WebRequest 返回 Forms 属性。我过去在 Powershell 5 中的做法:

$r = Invoke-WebRequest -Uri 'somewebsite.com' -SessionVariable f
$f
$form = $r.Forms[0]

$form.Fields["userName"] = "username"
$form.Fields["brokerPassword"] = "password"

$login = Invoke-WebRequest -Uri 'somewebsite.com' -WebSession $f -Method 
POST -Body $form.Fields

我在 Microsoft 文档中看到现在有一​​个-Form可以使用的参数,但我已经破解了几个小时,但收效甚微。

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-6

他们提供了两种可能的解决方案。

示例 1

$Uri = 'https://api.contoso.com/v2/profile'
$Form = @{
firstName  = 'John'
lastName   = 'Doe'
email      = 'john.doe@contoso.com'
avatar     = Get-Item -Path 'c:\Pictures\jdoe.png'
birthday   = '1980-10-15'
hobbies    = 'Hiking','Fishing','Jogging'
}
$Result = Invoke-RestMethod -Uri $Uri -Method Post -Form $Form

示例 2

$Body = @{
User = 'jdoe'
password = 'P@S$w0rd!'
}
$LoginResponse = Invoke-WebRequest 'http://www.contoso.com/login/' - 
SessionVariable 'Session' -Body $Body -Method 'POST'

$Session

$ProfileResponse = Invoke-WebRequest 'http://www.contoso.com/profile/' - 
WebSession $Session

$ProfileResponse

我都试过了,我当前的代码块是两者的组合,它至少让我失败了。

$username = 'useremail@gmail.com'
$password = 'p@ssw0rd'
$form = @{    
LoginForm_password = $password
LoginForm_username = $username
}
$result = Invoke-WebRequest 'https://www.podbean.com/login' - 
SessionVariable foo -Form $form -Method POST
$foo

$result | Get-Member | Format-table

这是我现在得到的错误。

调用 WebRequest :

403 禁止

Forbidden 您无权访问此服务器上的 /login。

在行:7 字符:11

  • $result = Invoke-WebRequest 'https://www.podbean.com/login' -SessionV ...
  •       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  • CategoryInfo : InvalidOperation: (Method: POST, Reque\u2026tent-Length: 357 }:HttpRequestMessage) [Invoke-WebRequest], HttpResponseException
  • FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

这实际上是我得到的最好的回应。

4

1 回答 1

3

为什么这可能不起作用

该站点使用了交叉请求站点伪造保护,它在表单正文中隐藏了一个偷偷摸摸的隐藏文本框元素,以确保有人在允许他们登录之前访问该站点。当您检查 HTML 时,您可以自己看到这一点。

<div style="display:none">
    <input type="hidden" value="f8cbcfecec95c2405222c3cd0f951f6783aa329c" name="kdsowie31j4k1jlf913">
</div>

display:none当我删除and的 CSS 样式元素时hidden,会出现隐藏的文本框。

在此处输入图像描述

当您正常登录该站点时,也会提交此值,这就是他们知道是您的方式。

由于到目前为止您使用 PowerShell 的请求尚未包含此临界值,这可能就是您遇到401其他未经授权的错误的原因。

您必须检索此令牌并提交它才能使其正常工作。 您不能只检索一次并将其硬编码到您的脚本中,因为它们的值通常在首次使用后或每隔几个小时过期。我测试过,看起来他们的过期很快。

检索令牌

检索这个令牌并不难。由于它是表单上唯一的隐藏元素,我们可以使用该属性来检索它。

$Request = Invoke-WebRequest -Uri https://www.podbean.com/login -SessionVariable Session -UseBasicParsing -UseDefaultCredentials
$TokenValue = ''
ForEach($field in $Request.InputFields){
    if ($field.type -eq 'hidden'){
        $TokenValue = [psCustomObject]@{Name=$field.name;Value=$field.Value}
    "Token value found! `n`t`tElement Name:`t$($TokenValue.Name)`n`t`tElement Value:`t$($TokenValue.Value)"
    }
}

当找到 Antiforgery/CRSF 令牌值时,这将回显以下内容。

在此处输入图像描述

然后,您可以像之前尝试做的那样将此值烘焙到您的表单中,并查看它引导您的位置。

  $header = @{
    '__RequestVerificationToken' = $TokenValue
}

$form = @{
    $TokenValue.Name = $TokenValue.Value
    LoginForm_password = $password
    LoginForm_username = $username
}

$result = Invoke-WebRequest 'https://www.podbean.com/login' -header $header -SessionVariable Session -Form $form -Method POST

你将不得不玩这个,但我认为这应该让你走上正确的道路。如果它不起作用,我会删除它$header,看看是否有帮助。我写了一篇关于这个主题的博客文章,如果您想阅读更多信息,请在此处了解更多信息。

更轻松的路线

PodBean 还提供了一个 API,您可以使用它来登录他们的服务。这将比您尝试做的简单得多,因为您可以执行简单的返回 JSON 的 Rest 方法调用,而不是表单抓取或 Web 自动化。10 次中有 9 次,如果存在 API,您应该使用它,原因很简单:

当您使用 API 时,您与服务的开发人员之间存在“合同”。他们将有效地承诺不会改变太多事情,以免破坏您的工作流程。

如果你为这个登录系统构建了一个精心设计的自动化系统,预计它会经常中断而令人讨厌,因为它们可能会更改登录表单、CSS 或任何会让你陷入困境的任何事情。

以下是如何开始使用他们的 API。 他们使用 oAuth 作为他们的身份验证平台。 如果您被 oAuth 卡住,我在这里为您提供了使用 PowerShell 和 oAuth 的指南。如果您继续 oAuth 路径并遇到困难,请在此处再发一篇文章,我会在此处为您提供帮助。

于 2019-06-24T14:26:42.407 回答