Сессия потеряна при переключении с HTTP на HTTPS в PHP

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

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

На сайте есть действующий SSL-сертификат, который может пригодиться, а может и не пригодиться.

Какой браузер вы используете? Есть ли какие-либо поддомены, такие как www.? Можете ли вы воспроизвести проблему в другом месте?

Unsigned 17.11.2011 00:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
64
1
68 324
16

Ответы 16

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

Какой браузер вы конкретно используете?

По умолчанию я ожидаю, что браузер будет рассматривать подключения к http и https как совершенно разные сеансы. Хотя по соглашению http: // someUrl / и https: // someUrl / будут указывать на одну и ту же страницу, это не гарантируется. У вас могут быть совершенно разные сайты, работающие на портах 80 (http) и 443 (https).

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

Простите неавторитетный ответ, но я подумал, что брослю свой 2c, так как ответов не так много.

Я бы вообще этого не ожидал. Проблема май возникает из-за проблем с маскированием с помощью путей / безопасных флагов. «Хотя условность такая ...» - Что за фигня? Нет, это действительно опасная практика.

symcbean 17.11.2011 16:55

@symcbean Тот факт, что оба URL-адреса указывают на одну и ту же страницу, не означает, что они оба доступны. Конечно, «безопасная» страница доступна только по https. Чего вы не видите, так это http // someUrl и https // someUrl, указывающих на совершенно другой контент, но это вполне возможно. У банка не будет http на защищенном сервере, но многие сайты будут привязывать 80 и 443 к одному и тому же серверу, как и запрашивающий.

codybartfast 18.11.2011 10:41

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

От PHP: session_start:

session_start() creates a session or resumes the current one based on the current session id that's being passed via a request, such as GET, POST, or a cookie

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

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

...

$currentSessionID = session_id();

...

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

...

session_id($aSessionID);

...

устанавливает файл cookie идентификатора сеанса в браузере на $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, на самом деле я не запускал эти сценарии, поэтому может быть одна или две опечатки, которые не позволяют им работать должным образом, как есть.

Использование дополнительно соленого хеша может обезопасить эту процедуру.

Gumbo 14.01.2009 19:47

Я не вижу здесь природы проблем безопасности - знаете какие-нибудь ресурсы, в которых они описаны?

bcoughlan 09.07.2010 14:36

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

Dean J 20.03.2011 04:25

@DeanJ - вы генерируете контрольную сумму на стороне сервера и анализируете ее по URL-адресу в качестве параметра. Например, вы можете сгенерировать хэш типа: $hash = md5($currentSessionID.'somesecretsalt'), а затем URL-адрес должен выглядеть как? Session = '. $ CurrentSessionID.' & Hash = '. $ Hash. Затем на целевом сайте вы должны проверить, выполняется ли md5 ($ _ GET ['session']. 'Somesecretsalt') == $ _GET ['hash']. Таким образом, вы можете сказать, что session_id был придуман не просто так. Идентификатор сеанса ДОЛЖЕН соответствовать сгенерированному сервером хешу (который практически невозможно взломать при использовании длинного значения соли).

Trolley 27.03.2013 18:07

+1 за то, что заметил проблему «переход от example.com/page.php к example.com/page.php» - это тоже было проблемой для меня. Я решил это, изменив свой файл .htaccess, чтобы полностью исключить www: RewriteCond% {HTTP_HOST} ^ www \ .example \ .com $ [NC] RewriteRule ^. * $ example.com% {REQUEST_URI} [R = 301, L]

JSP64 13.06.2014 21:18

Не могли бы вы также использовать одну и ту же технику для двух веб-сайтов на другом порту, например. mywebsite.com и mywebsite.com:80/index.html?

StackOverQuestions 12.01.2015 00:49

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

OP указал, что cookie был утерян при передаче к зашифрованного соединения. Флаг безопасный здесь не применяется.

Unsigned 17.11.2011 00:03

@Unsigned - Если вы переключаетесь на безопасную страницу и указываете странице использовать только безопасные файлы cookie сеанса, она должна создать новый безопасный файл cookie и не сможет использовать существующий незащищенный.

martinstoeckli 17.11.2011 01:36

@martinstoeckli - Верно. Однако настройка по умолчанию - off. Если бы это был on, файлы cookie не были бы отправлены на страницу HTTP, а это означает, что cookie никогда не должен существовать и там. Следовательно, файл cookie не является безопасным.

Unsigned 17.11.2011 03:23

@JW был прав, мне нужно время, чтобы разобраться, 'session_start (); setcookie (session_name (), session_id (), NULL, NULL, NULL, 0); ' устанавливает cookie как для http, так и для https, предотвращая потерю сеанса.

ontananza 09.08.2012 21:42

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

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

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

У нас тоже была эта проблема. Оказалось, это потому, что мы использовали патч Сухосин в нашей установке 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.

Еще мне нужно было отключить suhosin.cookie.cryptdocroot.

mrwalker 23.09.2011 19:37

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

sha1($string)

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

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

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

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

Я предлагаю сохранить значения в базе данных и сгенерировать ключ, затем сделать ссылку перенаправления, используя свой ключ, перенаправить страницу пользователей с параметром 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

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

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

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

вы можете установить тип движка таблицы в mysql, если хотите добиться максимальной производительности.

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

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

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

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

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

Uğur Gümüşhan 16.11.2011 03:16

@ UurGümüşhan: Приятно. Решение для базы данных будет работать медленнее по сравнению с кешем (относительно трафика), но оно будет постоянным. Как упоминалось в моем сообщении, мы используем хэш, который мы генерируем на стороне отправки (не ssl), для поиска данных на стороне приема (ssl).

Mike Purcell 16.11.2011 03:26

Чем это отличается от отправки идентификатора сеанса в URL-адресе (как указано в других ответах)? Не считая того, что хеш может быть длиннее и его сложнее угадать?

MrWhite 05.04.2013 17:14

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

Mike Purcell 05.04.2013 20:44

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

Ниже приведены некоторые приемы, с помощью которых вы можете поддерживать сеанс при переключении с HTTP на HTTPS.

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

  2. Идентификатор сеанса POST по POST

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

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

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

Надеюсь, вы что-то получите из моего ответа.

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

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

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

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

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

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

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

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

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

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

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

  2. Идентификатор сеанса 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

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

martinstoeckli 17.11.2011 13:57

У вас есть выделенный IP? в некоторых общих средах https и http маршрутизируются через разные серверы, поэтому при переключении фактически теряется доступ к файлам cookie, поскольку они находятся в разных доменах.

решения будут: выделенный IP

принудительное использование https на всех страницах в любое время

У меня была аналогичная проблема, однако это решение было для меня хорошим, возможно, поможет другим в будущем

добавьте это в свой php.ini

suhosin.session.cryptdocroot = Выкл.

suhosin.cookie.cryptdocroot = Выкл.

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

$_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();

У меня была эта проблема при переходе с http на https, и я смог решить эту проблему, изменив URL-адрес веб-сайта с http://example.com на https://www.example.com

добавление www к URL-адресу решило эту проблему для меня.

Спасибо.

Другие вопросы по теме