Получение HTML-страницы веб-сайта с помощью cURL с текущим сеансом и данными cookie на защищенной странице
вопрос полностью пересмотрен: февраль. 19-й
вещь, которую я хочу (короче):
я хотел бы получить HTML-страницу с помощью cURL, которая защищена логином пользователя (во время запроса cURL пользователь вошел в систему с правами на странице).
более подробно:
ситуация такова, что пользователь находится на странице как index.php?w=2344&y=lalala&x=something
который защищен (скриптом безопасности class.Firewizz.Security.php
). На этой странице есть "print as кнопка "pdf". Это отправляет пользователя на страницу getPDF.php
эта страница видит, откуда поступает запрос, и получает эту страницу с помощью cURL, и этот вывод будет отправлен в браузер как печать PDF.
но пока я устанавливаю переменную страницы статической в getPDF.php
страница, поэтому она не проверяет реферера, и я на 100% уверен, что страница, которую он пытается получить, правильна.
также вывод просто повторяется как есть и еще не преобразован в PDF, чтобы не мешать проблема.
ожидаемый результат теперь такой же, как и при переходе пользователя на страницу. разве это не так, пользователь ничего не получает.
что мы знаем?
Мы знаем, что $_SESSION
данные не отправляются в завиток, я знаю это точно, потому что я повторил $_SESSION
данные в выходном файле, в котором говорится, что они пусты.
после многих попыток у нас все еще нет решения, что так когда-либо, до сих пор нет данных "$_SESSION".
я не хотите скомпрометировать скрипт безопасности любым способом, поэтому решение " удалить ini_set('session.use_only_cookies', 1);
не то, что я ищу."
по запросу (для тех, которые предназначены для помощи) я могу отправить полные файлы сценариев, но я опубликую соответствующие фрагменты ниже.
class.Firewizz.Security.php
<?php
/*
* Firewizz UserLogin
*/
namespace Firewizz;
class Security
{
// Start the session, with Cookie data
public function Start_Secure_Session()
{
// Forces sessions to only use cookies.
ini_set('session.use_only_cookies', 1);
// Gets current cookies params
$cookieParams = session_get_cookie_params();
// Set Cookie Params
session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $this->isHTTPS, $this->deny_java_session_id);
// Sets the session name
session_name($this->session_name);
// Start the php session
session_start();
// If new session or expired, generate new id
if (!isset($_SESSION['new_session']))
{
$_SESSION['new_session'] = "true";
// regenerate the session, delete the old one.
session_regenerate_id(true);
}
}
// Check of user is logged in to current session, return true or false;
public function LOGGED_IN()
{
return $this->_login_check();
}
public function LOGOUT()
{
// Unset all session values
$_SESSION = array();
// get session parameters
$params = session_get_cookie_params();
// Delete the actual cookie.
setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
// Destroy session
session_destroy();
if (!headers_sent())
{
header("Location: " . $this->login_string, true);
}
else
{
echo '<script>window.location="/"</script>';
}
}
// Must pass variables or send to login page!
public function BORDER_PATROL($user_has_to_be_logged_in, $page_loaded_from_index)
{
$pass_border_partrol = true;
if (!$this->LOGGED_IN() && $user_has_to_be_logged_in)
{
$pass_border_partrol = false;
}
if (filter_input(INPUT_SERVER, "PHP_SELF") != "/index.php" && $page_loaded_from_index)
{
$pass_border_partrol = false;
}
// Kick to login on fail
if (!$pass_border_partrol)
{
$this->LOGOUT();
exit();
}
}
// Catch login, returns fail string or false if no errors
public function CATCH_LOGIN()
{
if (filter_input(INPUT_POST, "id") == "login" && filter_input(INPUT_POST, "Verzenden") == "Verzenden")
{
// Variables from form.
$email = filter_input(INPUT_POST, "email");
$sha512Pass = filter_input(INPUT_POST, "p");
// Database variables
$db_accounts = mysqli_connect($this->mySQL_accounts_host, $this->mySQL_accounts_username, $this->mySQL_accounts_password, $this->mySQL_accounts_database);
// Prepage sql
if ($stmt = $db_accounts->prepare("SELECT account_id, verified, blocked ,login_email, login_password, login_salt, user_voornaam, user_tussenvoegsel, user_achternaam FROM accounts WHERE login_email = ? LIMIT 1"))
{
$stmt->bind_param('s', $email); // Bind "$email" to parameter.
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
$stmt->bind_result($user_id, $verified, $blocked, $email, $db_password, $salt, $voornaam, $tussenvoegsel, $achternaam); // get variables from result.
$stmt->fetch();
$password = hash('sha512', $sha512Pass . $salt); // hash the password with the unique salt.
$tussen = ' ';
if ($tussenvoegsel != "")
{
$tussen = " " . $tussenvoegsel . " ";
}
$username = $voornaam . $tussen . $achternaam;
if ($stmt->num_rows == 1)
{ // If the user exists
// Check blocked
if ($blocked == "1")
{
return 'Deze acount is geblokkeerd, neem contact met ons op.';
}
// We check if the account is locked from too many login attempts
if ($this->_checkBrute($user_id, $db_accounts) == true)
{
// Account is locked
// Send an email to user saying their account is locked
return "Te vaak fout ingelogd,<br />uw account is voor " . $this->blockout_time . " minuten geblokkerd.";
}
else
{
if ($db_password == $password && $verified == 1)
{
// Password is correct!, update lastLogin
if ($stmt = $db_accounts->prepare("UPDATE accounts SET date_lastLogin=? WHERE account_id=?"))
{
$lastlogin = date("Y-m-d H:i:s");
$stmt->bind_param('ss', $lastlogin, $user_id); // Bind "$email" to parameter.
$stmt->execute();
$stmt->close();
}
$ip_address = $_SERVER['REMOTE_ADDR']; // Get the IP address of the user.
$user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.
$user_id = preg_replace("/[^0-9]+/", "", $user_id); // XSS protection as we might print this value
$_SESSION['user_id'] = $user_id;
$username = $username; // XSS protection as we might print this value
$_SESSION['username'] = $username;
$_SESSION['login_string'] = hash('sha512', $password . $ip_address . $user_browser);
// Login successful.
if ($this->MailOnLogin != FALSE)
{
mail($this->MailOnLogin, 'SECUREPLAY - LOGIN', $username . ' logged in to the secureplay platform..');
}
return false;
}
else
{
// Password is not correct
// We record this attempt in the database
$now = time();
$db_accounts->query("INSERT INTO login_attempts (userID, timestamp) VALUES (" . $user_id . ", " . $now . ")");
return "Onbekende gebruikersnaam en/of wachtwoord.";
}
}
}
else
{
return "Onbekende gebruikersnaam en/of wachtwoord.";
}
}
else
{
return 'SQL FAIL! ' . mysqli_error($db_accounts);
}
return "Onbekende fout!";
}
return false;
}
private function _checkBrute($user_id, $db_accounts)
{
// Get timestamp of current time
$now = time();
// All login attempts are counted from the past 2 hours.
$valid_attempts = $now - ($this->blockout_time * 60);
if ($stmt = $db_accounts->prepare("SELECT timestamp FROM login_attempts WHERE userID = ? AND timestamp > $valid_attempts"))
{
$stmt->bind_param('i', $user_id);
// Execute the prepared query.
$stmt->execute();
$stmt->store_result();
// If there has been more than 5 failed logins
if ($stmt->num_rows > $this->max_login_fails)
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
// Login Check if user is logged in correctly
private function _login_check()
{
// Database variables
$db_accounts = mysqli_connect($this->mySQL_accounts_host, $this->mySQL_accounts_username, $this->mySQL_accounts_password, $this->mySQL_accounts_database);
// Check if all session variables are set
if (isset($_SESSION['user_id'], $_SESSION['username'], $_SESSION['login_string']))
{
$user_id = $_SESSION['user_id'];
$login_string = $_SESSION['login_string'];
$username = $_SESSION['username'];
$ip_address = $_SERVER['REMOTE_ADDR']; // Get the IP address of the user.
$user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.
if ($stmt = $db_accounts->prepare("SELECT login_password FROM accounts WHERE account_id = ? LIMIT 1"))
{
$stmt->bind_param('i', $user_id); // Bind "$user_id" to parameter.
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
if ($stmt->num_rows == 1)
{ // If the user exists
$stmt->bind_result($password); // get variables from result.
$stmt->fetch();
$login_check = hash('sha512', $password . $ip_address . $user_browser);
if ($login_check == $login_string)
{
// Logged In!!!!
return $user_id;
}
else
{
// Not logged in
return false;
}
}
else
{
// Not logged in
return false;
}
}
else
{
// Not logged in
//die("f3");
return false;
}
}
else
{
// Not logged in
return false;
}
}
}
secured_page
<?php
require_once 'assets/class.Firewizz.Security.php';
if (!isset($SECURITY))
{
$SECURITY = new FirewizzSecurity();
}
// Check if user is logged in or redirect to login page;
$SECURITY->BORDER_PATROL(true, true);
// CONTENT bla bla
?>
getPDF.php
<?php
// Requires
require_once 'assets/class.FirePDF.php';
require_once 'assets/class.Firewizz.Security.php';
$SECURITY = new FirewizzSecurity();
$SECURITY->Start_Secure_Session();
// Html file to scrape, if this works replace with referer so the page that does the request gets printed.(prepend by security so it can only be done from securePlay
$html_file = 'http://www.website.nl/?p=overzichten&sort=someSort&s=67';
// Output pdf filename
$pdf_fileName = 'Test_Pdf.pdf';
/*
* cURL part
*/
// create curl resource
$ch = curl_init();
// set source url
curl_setopt($ch, CURLOPT_URL, $html_file);
// set cookies
$cookiesIn = "user_id=" . $_SESSION['user_id'] . "; username=" . $_SESSION['username'] . "; login_string=" . $_SESSION['login_string'] . ";";
// set cURL Options
$tmp = tempnam("/tmp", "CURLCOOKIE");
if ($tmp === FALSE)
{
die('Could not generate a temporary cookie jar.');
}
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
//CURLOPT_HEADER => true, //return headers in addition to content
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLINFO_HEADER_OUT => true,
CURLOPT_SSL_VERIFYPEER => false, // Disabled SSL Cert checks
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_COOKIEJAR => $tmp,
//CURLOPT_COOKIEFILE => $tmp,
CURLOPT_COOKIE => $cookiesIn
);
// $output contains the output string
curl_setopt_array($ch, $options);
$output = curl_exec($ch);
// close curl resource to free up system resources
curl_close($ch);
// output the cURL
echo $output;
?>
как мы тестируем
настоящее испытание сделано мимо войдите в систему и перейдите на правильную страницу, которую мы хотим получить с cURL, и проверьте, что он видит страницу(которая работает). Теперь мы запускаем getPDF.php
страница в новой вкладке. в котором мы видим пустую страницу из-за отказа безопасности. если добавить echo "session data:" . $_SESSION["login_string"]
; в сценарии безопасности мы видим, что переменные в $_SESSION пусты. Когда мы вставляем ту же строку в getPDF.php
мы видим его там. Таким образом, мы знаем, что факт не был передан cURL.
какой-то короткий информация.
- таким образом, с вышеуказанным кодом мы получаем пустую страницу;
- $_SESSION данные не отправлять;
- довольно уверен, что cookies не отправить либо;
- пробовал различные настройки cURL, ни один с успехом все равно;
- было бы идеально, если бы все данные $_SESSION и $_COOKIE были переданы;
- пробовал все, что сказано в комментариях или ответах.
3 ответов
Ok решено
после многих исследований.
данные Cookie передаются, но это не делает его данными сеанса.. Это было исправлено с помощью следующего метода:
private function Cookie2Session($name)
{
if (filter_input(INPUT_COOKIE, $name))
{
$_SESSION[$name] = filter_input(INPUT_COOKIE, $name);
}
}
// following lines put within the BORDER_PATROL Method
if (filter_input(INPUT_COOKIE, 'pdfCurl'))
{
$this->Cookie2Session('user_id');
$this->Cookie2Session('username');
$this->Cookie2Session('login_string');
$this->Cookie2Session('REMOTE_ADDR');
$this->Cookie2Session('HTTP_USER_AGENT');
$_SESSION['new_session'] = "true";
}
небольшое изменение метода _login_check()
// Login Check if user is logged in correctly
private function _login_check()
{
// Database variables
$db_accounts = mysqli_connect($this->mySQL_accounts_host, $this->mySQL_accounts_username, $this->mySQL_accounts_password, $this->mySQL_accounts_database);
// Check if all session variables are set
if (isset($_SESSION['user_id'], $_SESSION['username'], $_SESSION['login_string']))
{
$user_id = $_SESSION['user_id'];
$login_string = $_SESSION['login_string'];
$username = $_SESSION['username'];
$ip_address = $_SERVER['REMOTE_ADDR']; // Get the IP address of the user.
$user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.
// =====>> add this code, because cURL req comes from server. <<=====
if (isset($_SESSION["REMOTE_ADDR"]) && ($_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR']))
{
$ip_address = $_SESSION["REMOTE_ADDR"];
}
// {rest of code}
небольшие обновления :
<?php
// Requires
require_once 'assets/class.FirePDF.php';
require_once 'assets/class.Firewizz.Security.php';
$SECURITY = new \Firewizz\Security();
$SECURITY->Start_Secure_Session();
// Html file to scrape, if this works replace with referer so the page that does the request gets printed.(prepend by security so it can only be done from securePlay
$html_file = 'http://www.secureplay.nl/?p=overzichten&sort=SpeelplaatsInspecties&s=67';
// Output pdf filename
$pdf_fileName = 'Test_Pdf.pdf';
/*
* cURL part
*/
// create curl resource
$ch = curl_init();
// set source url
curl_setopt($ch, CURLOPT_URL, $html_file);
// set cookies
$cookiesIn = "user_id=" . $_SESSION['user_id'] . "; username=" . $_SESSION['username'] . "; login_string=" . $_SESSION['login_string'] . "; pdfCurl=true; REMOTE_ADDR=" . $_SERVER['REMOTE_ADDR'] . "; HTTP_USER_AGENT=" . $_SERVER['HTTP_USER_AGENT'];
$agent = $_SERVER['HTTP_USER_AGENT'];
// set cURL Options
$tmp = tempnam("/tmp", "CURLCOOKIE");
if ($tmp === FALSE)
{
die('Could not generate a temporary cookie jar.');
}
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
//CURLOPT_HEADER => true, //return headers in addition to content
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLINFO_HEADER_OUT => true,
CURLOPT_SSL_VERIFYPEER => false, // Disabled SSL Cert checks
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_COOKIEJAR => $tmp,
//CURLOPT_COOKIEFILE => $tmp,
CURLOPT_COOKIE => $cookiesIn,
CURLOPT_USERAGENT => $agent
);
// $output contains the output string
curl_setopt_array($ch, $options);
$output = curl_exec($ch);
// close curl resource to free up system resources
curl_close($ch);
// output the cURL
echo $output;
?>
с вышеуказанными знаниями вы можете полностью использовать cURL для посещения безопасной страницы с текущими данными сеанса только с незначительными безопасность.
так что ваши $cookiesIn
должен быть определен ваш cookies. Я сделаю пример на основе вашего кода:
$cookiesIn = "user_id=" . $_SESSION['user_id'] . "; username=" . $_SESSION['username'] . "; login_string=" . $_SESSION['login_string'] . ";";
попробуйте установить это на странице pdfCreator. Заменить $cookiesIn = "";
С строку выше и посмотреть, если это дает иной результат.
кроме того, вот отличная ссылка для опции cURL cookie
:
https://curl.haxx.se/libcurl/c/CURLOPT_COOKIE.html
если вы хотите, чтобы все куки просто были отправлены вместо обозначая их, используйте этот код:
$tmp = tempnam("/tmp", "CURLCOOKIE");
if($tmp === FALSE) die('Could not generate a temporary cookie jar.');
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
//CURLOPT_HEADER => true, //return headers in addition to content
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLINFO_HEADER_OUT => true,
CURLOPT_SSL_VERIFYPEER => false, // Disabled SSL Cert checks
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_COOKIEJAR => $tmp,
CURLOPT_COOKIEFILE => $tmp,
);
этот код будет сбрасывать все текущие куки-файлы для использования в cURL, с . Тогда, когда мы обозначим COOKIEFILE
, мы обозначаем, где cURL должен искать, чтобы включить куки с запросом.
тем не менее, я избавился от $cookiesIn
ссылка, поскольку она не нужна, если вы используете код выше.
в этом случае, если алгоритм управления сеансом является звуковым, вы просто хотите изменить формат, в котором отправляется страница.
использование cURL для повторной выборки страницы-один из способов сделать это, но это похоже на проблему XY; на самом деле вы не хочу чтобы использовать cURL, вы хотите контролировать выходной формат, HTML или PDF.
одним из жизнеспособных вариантов было бы перезагрузка страница после добавления определенного параметра, который будет введен в разделе контекст и изменение выходной функции. Например, вы можете обернуть всю страницу в пузырь буферизации вывода:
// Security checks as usual, then:
if (array_key_exists('output', $_GET)) {
$format = $_GET['output']; // e.g. "pdf"
// We could check whether the response handler has a printAs<FORMAT> method
switch ($format) {
case 'pdf': $outputFn = 'printAsPDF'; break;
default:
throw new \Exception("Output in {$format} format not supported");
}
ob_start($output);
}
// Page is generated normally
вывод 'printAsPDF' получит содержимое страницы и будет использовать что-то вроде dompdf или wkhtml2pdf, чтобы отформатировать его как PDF-файл, добавить соответствующие заголовки типа контента и вернуть отформатированный PDF.
безопасность остается прежней, и модификация фактически может быть реализована на этапе декодирования запроса. Переменная состояния с в настоящее время используемый формат вывода может быть доступен для других объектов, что позволяет им вести себя по-разному в зависимости от ситуации (например, функция generateMenu() может выбрать немедленное возвращение вместо отображения чего-то, что не имело бы смысла в PDF).