Как правильно перенять куки при редиректе в php
Проблема в следующем: пытаюсь получить запрос поиска с сайта, но т.к. не залогинен, выполняется редирект. Каждая страница перезаписывает cookie s
в браузере это работает следующим образом:
https://site.com/search?q=abc
GET https://site.com/search?q=abc 302: GET https://site.com/login set-cookie: s=123
GET https://site.com/login?back_url=https://site.com/search?q=abc set-cookie: s=234
<login-form> POST with cookie s=234 302: GET https://site.com/search?q=abc
нужно повторить из php, получаю текст страницы через
file_get_contents('https://site.com/search?q=abc');
в результате после авторедиректа получаю текст страницы для login
Вытаскиваю из заголовка ответа Set-cookie
и думается мне, что получаю cookie s=123 (т.е. от первого вызова, а не от редиректа)
т.к. при следующем POST мне сообщает сервер, что куки не правильные
{косяк может быть в этом месте...} может такое быть? И если может, как получить правильный кук после редиректа?
Проверить это не получается, т.к. если я включаю какой-нибудь сниффер, то скрипт вылетает с ошибкой:
file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed
file_get_contents(): Failed to enable crypto
file_get_contents($url): Failed to open stream: operation failed
Пробовал это обойти, добавлял в $opts
'ssl' => array('cafile' => 'cacert.pem',
'verify_peer'=> true,
'verify_peer_name'=> true
)
но это не помогло...
POST делаю вот так примерно
$params = //http_build_query( //для POST не необходимо
array(
'utf8' => '✓',
'back_url' => $back_url,
'authenticity_token' => $token,
'username' => 'aaa',
'password' => 'bbb',
'login' => 'Login'
);
//);
$cookie = get_s_cookie;
$opts = array('http' => array('method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded'
.'\r\nCookie: '.$cookie //из Set-Cookie
,
'content' => $params,
'ignore_errors' => true //чтобы текст ошибки вообще увидеть
)
);
$context = stream_context_create($opts);
$source = file_get_contents('https://site.com/login', false, $context);
Проверял в postman, всё работает, но там куки перецепляются автоматом.
Куки вытаскивал так: (это наверняка тот ещё изврат и может это автоматизируется на самом деле каким-нибудь методом, но я не нашёл ничего более логичного)
function get_s_cookie($response_header){
//s=VVEzcTllSGVlamNPMmRhN29m--9fc2868474a4e4a3fb2d98036e4ad2d00e1a29b4; path=/; HttpOnly
foreach ($response_header as $header_item){
//echo 'item: '.$header_item.'<br>';
if(stripos($header_item, 'Set-Cookie:') !== false){
list($set_cookie, $cookie_value) = explode(':', $header_item);
$result_with_params = $cookie_value;
list($cookie_name, $cookie_value) = explode('=', trim($cookie_value));
if($cookie_name == 's'){
list($cookie_value, $path) = explode(';', $cookie_value);
$result_without_params = $cookie_name.'='.$cookie_value;
return $result_without_params;
//return $result_with_params;
break;
}
}
}
}
$result_with_params в виде s=VVEzcTllSGVlamNPMmRhN29m--9fc2868474a4e4a3fb2d98036e4ad2d00e1a29b4; path=/; HttpOnly
$result_without_params в виде s=VVEzcTllSGVlamNPMmRhN29m--9fc2868474a4e4a3fb2d98036e4ad2d00e1a29b4
{косяк может быть в этом месте...} что из этого правильнее передавать в header не знаю, пробовал и так и так и оба варианта не работают
PS: на практике это попытка залогиниться в redmine, если у кого есть, можете попробовать на реальном примере
https://redmine.server.com/projects/v-x/search?utf8=%E2%9C%93&q=preissuche&scope=subprojects&all_words=1&wiki_pages=1&commit=Suche