Как войти на сайт, используя новый параметр -form в pwsh
PowerShell 6.2.1 не возвращает свойство Forms, используя Invoke-WebRequest. В документе Microsoft Doc я вижу, что теперь есть параметр -Form, который вы можете использовать, но я взломал его уже несколько часов с очень небольшим успехом.
Как я делал это в 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 Doc я вижу, что теперь есть параметр -Form, который вы можете использовать, но я взломал его уже несколько часов с очень небольшим успехом.
Они предоставили два возможных решения.
Пример 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
Это ошибка, которую я сейчас получаю.
Invoke-WebRequest:
403 Запрещено
Запрещено У вас нет разрешения на доступ / вход на этом сервере.
В строке:7 символов: 11 + $ result = Invoke-WebRequest ' https://www.podbean.com/login' -SessionV... + ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CategoryInfo: InvalidOperation: (Метод: POST, Reque\u2026tent-Length: 357 }:HttpRequestMessage) [Invoke-WebRequest], HttpResponseException + FullyQualifiedErrorId: WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCmand
На самом деле это лучший ответ, который я получил.
1 ответ
Почему это, вероятно, не работает
На этом сайте использовалась защита от фальсификации сайтов с перекрестными запросами, которая скрывает скрытый скрытый элемент текстового поля в теле формы, чтобы гарантировать, что кто-то заходит на сайт, прежде чем разрешить им войти в систему. Вы можете убедиться в этом сами, просматривая HTML.
<div style="display:none">
<input type="hidden" value="f8cbcfecec95c2405222c3cd0f951f6783aa329c" name="kdsowie31j4k1jlf913">
</div>
Когда я удаляю элементы стиля CSS display:none
а также 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, который вы можете использовать для входа в свои сервисы. Это было бы намного проще, чем то, что вы пытаетесь сделать, потому что вместо очистки форм или веб-автоматизации вы могли бы делать простые вызовы методов Rest, которые возвращали бы JSON. 9 раз из 10, если API существует, вы должны использовать его по этой простой причине:
Когда вы используете API, между вами и разработчиком сервиса существует "контракт". Они пообещают не слишком сильно что-то менять, чтобы не нарушать ваш рабочий процесс.
Если вы создаете сложную автоматизацию для этой системы входа в систему, ожидайте, что она сломается достаточно часто, чтобы раздражать, так как они могут изменить форму входа в систему, CSS или любую из множества вещей, которые могут привести вас к смерти.
Вот как можно начать с их API вместо этого. Они используют oAuth в качестве платформы аутентификации. У меня есть руководство по использованию PowerShell и oAuth, если вы застряли с oAuth. Если вы продолжите идти по пути oAuth и застрянете, сделайте еще один пост здесь, и я помогу вам там.