Ранее в этой серии постов:
...17.
PowerShell и ЖЖ: аутентификация с «cookie», интерфейс «flat»18.
PowerShell: улучшаю преобразование данных из XML-RPC в хеш-таблицу19.
PowerShell: улучшаю преобразование данных из хеш-таблицы в XML-RPC Окружение: операционная система «Windows 10», программа-оболочка «PowerShell» версии 7.
0. Подготовка вспомогательных функций
Преобразование хеш-таблицы с параметрами в формат XML-RPC (
подробнее)
function toXMLScalar($val) {
$type = $val.GetType().Name
if ($type -eq "Int32") {$type = "int"} else {
$type = "string"
$val = $val -replace '&', '&'
$val = $val -replace '<', '<'
}
"<{0}>{1}" -f $type, $val
}
function toXMLValue($val) {
$val = if ($val -is [System.Array]) {
toXMLArray $val
} elseif ($val.GetType().Name -eq "Hashtable") {
toXMLStruct $val
} else {
toXMLScalar $val
}
"{0}" -f $val
}
function toXMLArray($arr) {
$values = foreach ($elem in $arr) { toXMLValue $elem }
$values = -join $values
"{0}" -f $values
}
function toXMLMember($key, $val) {
$val = toXMLValue $val
"{0}{1}" -f $key, $val
}
function toXMLStruct($hashT) {
$members = foreach ($key in $hashT.Keys) {
if ($key -ne "mode") {
toXMLMember $key $hashT[$key]
}
}
$members = -join $members
"{0}" -f $members
}
function toXML($hashT) {
$xml = -join @(
''
"LJ.XMLRPC.{0}"
"
{1}"
)
$value = toXMLValue $hashT
$xml -f $hashT["mode"], $value
}
Извлечение данных из формата XML-RPC в хеш-таблицу (
подробнее)
function toHashTable($strXml, $xpath) {
$arr = (Select-Xml -Content $strXml -XPath $xpath).node
$hash = @{}
$res = $arr | ForEach-Object { $hash[$_.name] = $_.value.FirstChild."#text" }
return $hash
}
Получение хеш-суммы строки по указанному алгоритму
function getHash($str, $alg) {
$stringAsStream = [System.IO.MemoryStream]::new()
$writer = [System.IO.StreamWriter]::new($stringAsStream)
$writer.write($str)
$writer.Flush()
$stringAsStream.Position = 0
(Get-FileHash -InputStream $stringAsStream -Algorithm $alg).Hash.ToLower()
}
1. Получение «cookie» от веб-сервера ЖЖ (начало сессии)
$body = @{
mode = "getchallenge"
}
$body = toXML($body)
$Response = Invoke-WebRequest -URI "
https://www.livejournal.com/interface/xmlrpc" `
-Body $body -Method "POST"
$xpath = "/methodResponse/params/param/value/struct/*"
$params = toHashTable $Response.Content $xpath
$hPass = getHash "пароль" "MD5"
$hResp = getHash ($params["challenge"] + $hPass) "MD5"
$body = @{
mode = "sessiongenerate"
username = "vbgtut"
auth_method = "challenge"
auth_challenge = $params["challenge"]
auth_response = $hResp
}
$body = toXML($body)
$Response = Invoke-WebRequest -URI "
https://www.livejournal.com/interface/xmlrpc" `
-Body $body -Method "POST"
$xpath = "/methodResponse/params/param/value/struct/*"
$params = toHashTable $Response.Content $xpath
$ljsession = $params["ljsession"]
$ljsession
v2:u31363138:s296:avxfFYeUo73:g95e7b87fd292eb786d17af3490a69d8d1a5c3ebf//1
2. Рабочая часть сессии (на примере получения одного поста журнала)
$body = @{
mode = "getevents"
username = "vbgtut"
auth_method = "cookie"
selecttype = "one"
itemid = 148
ver = 1
}
$body = toXML($body)
$headers = @{
"X-LJ-Auth" = "cookie"
Cookie = "ljsession=$ljsession"
}
$Response = Invoke-WebRequest -URI "
https://www.livejournal.com/interface/xmlrpc" `
-Body $body -Method "POST" -Headers $headers
$xpath = "/methodResponse/params/param/value/struct/member/value/array/data/value/struct/*"
$params = toHashTable $Response.Content $xpath
$params["url"]
https://vbgtut.livejournal.com/37952.html 3. Завершение сессии, инициированное веб-клиентом
3.1. Завершение сессии по ее идентификатору
$res = $ljsession -match '^.+:.+:.(.+):.+:.+$'
$body = @{
mode = "sessionexpire"
username = "vbgtut"
auth_method = "cookie"
expire = @($Matches[1]) # в массиве можно указать ряд идентификаторов сессий
}
$body = toXML($body)
$headers = @{
"X-LJ-Auth" = "cookie"
Cookie = "ljsession=$ljsession"
}
$Response = Invoke-WebRequest -URI "
https://www.livejournal.com/interface/xmlrpc" `
-Body $body -Method "POST" -Headers $headers
Нет смысла извлекать данные HTTP(S)-ответа, так как при успешном выполнении удалённой функции «sessionexpire» возвращается пустая хеш-таблица (struct). Проверить, действительно ли завершилась сессия, можно, повторив шаг 2 (рабочую часть сессии), на котором, если сессия завершилась, будет получено сообщение о неправильном пароле.
3.2. Завершение всех открытых сессий для указанного пользователя
$body = @{
mode = "sessionexpire"
username = "vbgtut"
auth_method = "cookie"
expireall = "true" # не массив в отличие от предыдущего блока кода
}
$body = toXML($body)
$headers = @{
"X-LJ-Auth" = "cookie"
Cookie = "ljsession=$ljsession"
}
$Response = Invoke-WebRequest -URI "
https://www.livejournal.com/interface/xmlrpc" `
-Body $body -Method "POST" -Headers $headers
Нет смысла извлекать данные HTTP(S)-ответа, так как при успешном выполнении удалённой функции «sessionexpire» возвращается пустая хеш-таблица (struct). Проверить, действительно ли завершилась сессия, можно, повторив шаг 2 (рабочую часть сессии), на котором, если сессия завершилась, будет получено сообщение о неправильном пароле.
4. Пример проверки того, что определенная сессия завершена (повтор шага 2)
$ljsession
v2:u31363138:s296:avxfFYeUo73:g95e7b87fd292eb786d17af3490a69d8d1a5c3ebf//1
$body = @{
mode = "getevents"
username = "vbgtut"
auth_method = "cookie"
selecttype = "one"
itemid = 148
ver = 1
}
$body = toXML($body)
$headers = @{
"X-LJ-Auth" = "cookie"
Cookie = "ljsession=$ljsession"
}
$Response = Invoke-WebRequest -URI "
https://www.livejournal.com/interface/xmlrpc" `
-Body $body -Method "POST" -Headers $headers
$xpath = "/methodResponse/fault/value/struct/*"
$params = toHashTable $Response.Content $xpath
$params["faultString"]
Invalid password
В этом посте - только код и короткие пояснения. Основная часть пояснений уже дана для работы через протокол «flat» в
одном из предыдущих постов (принципиально работа через разные интерфейсы ничем не отличается, разница есть в ряде мелочей и в формате отправляемых и получаемых данных).