Сессия потерялась при переходе с HTTP на HTTPS в PHP - PullRequest
62 голосов
/ 14 января 2009

При отправке пользователя на страницу оформления заказа они переключаются с http://sitename.com на https://sitename.com.

В результате $_SESSION переменные теряются.

На сайте имеется действительный сертификат SSL, который может или не может быть полезным.

Ответы [ 15 ]

69 голосов
/ 14 января 2009

Когда вы переключаетесь между службами HTTP и HTTPS на одном и том же сервере, ваш идентификатор сеанса HTTP не передается в сеанс HTTPS. Вы можете установить его, передав идентификатор сессии со страницы HTTP на страницу HTTPS одним из трех возможных способов:

С PHP: сессия_запуска :

session_start() создает сеанс или возобновляет текущий на основе в текущем сеансе идентификатор, который передается через запрос, такой как ПОЛУЧИТЬ, ПОЧТУ или печенье

Когда вы используете сеансы, вы обычно запускаете свой скрипт с session_start(). Если в браузере установлен файл cookie с идентификатором сеанса, session_start() будет использовать этот идентификатор сеанса. Если в браузере не установлен файл cookie идентификатора сеанса, session_start() создаст новый.

Если идентификатор сеанса не установлен (в вашем примере браузер создает новый файл cookie идентификатора сеанса для сеанса HTTPS), вы можете установить его с помощью функции session_id(). session_id() также удобно возвращает идентификатор сеанса в виде строки. Так

...

$currentSessionID = session_id();

...

устанавливает переменную $currentSessionID равной текущему идентификатору сеанса, а

...

session_id($aSessionID);

...

устанавливает cookie-файл sessionID в браузере на $aSessionID. с PHP: session_id

Вот пример с двумя сценариями. Доступ к одному осуществляется через HTTP, а к другому - по HTTPS. Они должны находиться на одном сервере для хранения данных сеанса.

Скрипт 1 (HTTP) :

<?php

// This script will create a session and display a link to your secure server address
// to transfer your session ID. In this example, the secure page to receive the session
// ID is located at http://www.yoursite.com/safePages/securePage.php

// Start a session using the current session ID stored in a cookie, or create
// a new session if none is set.
session_start();

$currentSessionID = session_id();

// Set a variable that will be retrieved with the HTTPS script.
$_SESSION['testvariable'] = 'It worked';

// $secureServerDomain is the domain of your secure server
$secureServerDomain = 'www.yoursite.com';

// $securePagePath is the path to the page that will receive and set the session ID.
$securePagePath = '/safePages/securePage.php'

echo '<a href="https://' . $secureServerDomain . $securePagePath . '?session="' . $currentSessionID . '">Click here to transfer your session to the secure server</a>';

?>

Скрипт 2 (HTTPS) :

<?php

// Retrieve the session ID as passed via the GET method.
$currentSessionID = $_GET['session'];

// Set a cookie for the session ID.
session_id($currentSessionID);

// Start a session.
session_start();

// Test retrieval of variable set when using HTTP.
if (!empty($_SESSION['testvariable'])) {
      echo $_SESSION['testvariable'];
} else {
      echo 'It did not work.';
}

?>

Чтобы это работало, серверы HTTP и HTTPS должны использовать один и тот же субстрат для хранения данных сеанса (т. Е. Для обработчика файлов по умолчанию запуск на том же физическом компьютере с тем же php.ini). Здесь есть некоторые недостатки в безопасности, поэтому я бы не стал использовать этот код для передачи конфиденциальной информации. Это просто пример работоспособности.

Когда я столкнулся с этой проблемой раньше, я придумал вышеупомянутое как быстрое решение, но я только что вспомнил первоначальную причину проблемы. Я шел от http://www.example.com/page.php до https://example.com/page.php (обратите внимание на отсутствие "www"). Убедитесь, что http://www.example.com/page.php будет ссылаться на https://www.example.com/page.php, а http://example.com будет ссылаться на https://example.com/page.php.

PS, я на самом деле не запускал эти скрипты, так что может быть одна или две опечатки, которые мешают им работать должным образом.

16 голосов
/ 14 января 2009

Звучит так, как будто сессионный cookie установлен как безопасный. Куки имеют флаг «безопасный» , который, если задано значение true, означает, что куки не будут отправляться на сайты, не являющиеся https. PHP, вероятно, использует это для своих сессионных куки. Вы можете изменить это с помощью функции session_set_cookie_params или с помощью параметра session.cookie_secure в php.ini.

12 голосов
/ 17 июля 2010

У нас тоже была эта проблема. Оказалось, потому что мы использовали патч suhosin в нашей установке PHP. Мы исправим это, установив suhosin.session.cryptdocroot = Off в /etc/php.d/suhosin.ini.

Руководство по suhosin о suhosin.session.cryptdocroot см. http://www.hardened -php.net / suhosin / configuration.html # suhosin.session.cryptdocroot .

Первоначально мы нашли исправление из этого поста в блоге: http://www.yireo.com/blog/general-news/315-switch-between-http-and-https-looses-php-session.

6 голосов
/ 16 ноября 2011

В следующем решении предполагается, что защищенные и незащищенные серверы имеют доступ к одним и тем же внутренним службам (кэш, хранилище баз данных и т. Д.).

Мы столкнулись с этой же проблемой, когда отправляли пользователя в нашу кассу, когда он делал покупки. Чтобы решить эту проблему, мы создали слой кэширования и кэшировали все соответствующие данные. Например, мы собирали идентификаторы продуктов и пользователей из значений сеанса, сериализовывали их, создавали хэш и, наконец, сохраняли данные сеанса в кеше, используя хеш в качестве ключа. Затем мы перенаправим пользователя на защищенный сайт с хешем в URL.

Когда пользователь попадет на защищенный сайт, мы попытаемся извлечь данные из кэша на основе хэша. Затем с помощью идентификатора пользователя и идентификатора продукта мы можем загрузить все данные о ценах и описании из базы данных и представить их пользователю для окончательной проверки заказа.

Существует наследственный риск, заключающийся в том, что данные в кэше изменчивы, но у нас никогда не было проблем с этим, поскольку перенаправление происходит быстро.

1 голос
/ 17 ноября 2011

Вы можете управлять сеансом между HTTP на HTTPS или HTTPS на HTTP:

  1. Передача идентификатора сеанса между страницами с помощью GET

  2. ID сеанса POST по POST

  3. Использование файлов для сохранения сеансов

  4. Использование файлов cookie для сеансов

  5. Использование базы данных для сохранения сеанса

Приведенный ниже пример может использоваться для передачи с использованием GET….

Файл: http.php ...............

<?php

session_start();

$sessionID = session_id();

$_SESSION['demo'] = ‘Demo session between HTTP HTTPS’;

echo ‘<a href=”https://www.svnlabs.com/https.php?session=’.$sessionID.’”>Demo session from HTTP to HTTPS</a>’;

?>

Файл: https.php ...............

<?php

$sessionID = $_GET['session'];

session_id($sessionID);

session_start();

if (!empty($_SESSION['demo'])) {
echo $_SESSION['svnlabs'];
} else {
echo ‘Demo session failed’;
}

?>

IE7: эта страница содержит как безопасные, так и незащищенные элементы

Вы должны использовать относительный путь для всех статических ресурсов на странице, таких как css, js, images, flash и т. Д., Чтобы избежать защищенных и незащищенных элементов сообщения IE…

IE Message IE сообщение

1 голос
/ 16 ноября 2011

Подумайте об использовании HTTPS для всех страниц, это самый простой способ избежать этой проблемы, и это повысит безопасность вашего сайта.

Если SSL для всех страниц не подходит для вас, вы можете использовать этот подход: Переключение между страницами HTTP и HTTPS с помощью безопасной сессии-cookie . Идея заключается в том, что вы оставляете cookie сессии незащищенными (и, следовательно, доступными для страниц HTTP и HTTPS), но имеете второй безопасный cookie для обработки аутентификации. Это хороший способ отделить два вопроса: «поддержание сеанса» и «аутентификация».

1 голос
/ 16 ноября 2011

Я бы рекомендовал, в дополнение к тому, что большинство здесь заявили о передаче зашифрованной информации, смотреть на нее так же, как если бы вы передавали конфиденциальную информацию через сторонний API. Как вы знаете, кто-то не подделывает запрос? Существует много протоколов для подлинного подтверждения подлинности запроса, в зависимости от того, насколько чувствительны ваши настройки. Вы открываете себя для взломанных аккаунтов, если не будете осторожны.

Даже если он находится на том же сервере, учтите следующее:

Когда кто-то переходит по ссылке, действию формы и т. Д., Которые передаются по зашифрованному ключу, что может помешать кому-либо прослушать его, прежде чем он попадет на защищенную версию вашего сайта? Если бы я был в общественном месте WIFI, это не было бы слишком надуманным. Я мог бы притвориться вашим сайтом, перенаправить запросы на свой ноутбук, взять токен и перенаправить посетителя туда, куда он пришел. Они предположили бы, что это был сбой, и не имели бы понятия. Теперь я могу войти в систему как они, и, возможно, пойти купить вещи на 10000 долларов с их кредитной картой в файл и отправить его куда-нибудь еще. Степень осторожности, которую вы принимаете здесь, должна соответствовать степени чувствительности.

Кроме того, убедитесь, что у вас истек срок действия ваших токенов (только одно использование, через X секунд и т. Д.), Но я бы также рассмотрел возможность использования шаблона Post-Redirect-Get на обоих концах, т.е.

Не показывать прямую ссылку на странице или в форме незащищенного сайта, но показывать ссылку, которая затем перенаправляет на бэкэнд (и обрабатывает весь токен / шифрование). Когда вы достигнете защищенной версии, сделайте то же самое (не оставляйте параметр «? Token = asdfjalksfjla» просто в URL; перенаправьте его).

Итак, формальные системы на основе токенов были разработаны для решения этой самой проблемы, но реализация OAuth только для этого может быть излишней. Потратьте некоторое время на планирование потенциальных уязвимостей перед выполнением. Просто потому, что было бы очень трудно угадать токен, не означает, что это невозможно (или не могло быть столкновений и т. Д.), Поэтому планируйте соответственно.

Вам также может понадобиться более сложная система управления сеансами, чем встроенные обработчики PHP. Я не знаю, можно ли заставить PHP продолжать сеанс через несколько посещений (переключение протоколов обрабатывается таким образом).

1 голос
/ 15 ноября 2011

Вы не можете передавать значения сеанса между разными доменами. Вы должны использовать http post-get или базу данных для передачи ваших значений. В целях безопасности вы можете объединить все свои значения в строку и использовать

sha1($string)

и опубликуйте его вместе со своими значениями и вычислите sha1 для значений, которые получает другая страница, затем сравните хэши.

Метод Post в разных доменах приводит к тому, что браузеры показывают сообщение безопасности, поэтому не используйте его.

Использование url для метода get небезопасно, вам потребуется запросить пароль на перенаправленной странице для разрешения параметров get в вашей системе.

Не используйте куки, если вам нужна безопасность.

Я предлагаю сохранить значения в базе данных и сгенерировать ключ, затем создать ссылку для перенаправления с помощью вашего ключа, перенаправить страницу пользователей с параметром get, содержащим ключ, а затем перенаправить пользователя на страницу получает этот ключ, получает данные и удаляет ключ. вы можете сгенерировать ключ с помощью sha1

PAGE 1---
$key=sha1($allvalsconcat);
//insert your session values to a database also the key in a column
header("Location: page2.php?key=".$key);

PAGE 2---
// select from database where key=$_GET["key"];
// delete from table where key=$key

это довольно безопасно.

вещи, которые могут произойти: скрипт ввода случайных значений для параметра «ключ», чтобы ваш сайт загружал данные в вашу память?

Этого не произойдет, потому что вы удаляете запись после ее использования. Некоторое распространенное заблуждение заключается в том, что получение значений небезопасно и всегда следует избегать.

Вы можете установить тип движка таблицы на «memory» в mysql, если вы хотите улучшить производительность.

1 голос
/ 27 февраля 2009

Похоже, что ваш файл cookie сеанса создается с флагом безопасности, но есть что-то с URL вашей страницы оформления заказа, из-за которого файл cookie сеанса не передается.

Или, возможно, ваш файл cookie сеанса не является безопасным - просто URL-адрес страницы оформления заказа отличается (http://mysite.com против http://www.mysite.com), что браузер не отправляет файл cookie.

Если вы хотите больше узнать о переключении с http на https и наоборот - посмотрите на мою рецензию на выборочный ssl : -)

0 голосов
/ 18 сентября 2016

У меня есть решение по этому .. Попробуйте.

$_SESSION['test'] = 'test';
session_regenerate_id(true);

header("Location: /");// the header must be sent before session close
session_write_close(); // here you could also use exit();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...