2011-12-27 4 views
10

Я хотел бы знать, есть ли способ предотвратить отправку cookie PHP при вызове session_start().Предотвратить php session_start(), чтобы отправить файл cookie

Мой случай использования для оптимизации сайта:

  • (1a) Я первым открыть сеанс/отправить заголовки.
  • (1b) Затем генерируйте и выводите текстовое содержимое.
  • (1c) Чтобы улучшить сеанс чтения/записи, я вызываю «session_write_close», как только мне больше не нужно писать в сеансе.
  • (2) Наконец, у меня есть процесс рендеринга после страницы (для статистики), для которого требуется доступ на запись к сеансу. Сеанс закрыт, я не могу снова вызвать session_start(), так как он отправляет файл cookie, и для него это поздно. Это сложный процесс вычисления, поэтому я должен сделать это после отправки страницы клиенту.

Клиент уже получил сеансовое печенье. Поэтому мне не нужно session_start(), чтобы отправить новый (и избыточный).

Кто-нибудь знает способ перехватить файл cookie или что-то подобное? Конечно, я хочу избежать «Не могу отправить сессию cookie - уже отправленные заголовки». Эта ошибка невидима для пользователя, поскольку страница уже визуализирована, но в журналах она выглядит уродливой.

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

ответ

11

Я хотел бы знать, есть ли способ предотвратить отправку cookie PHP при вызове session_start().

Да, есть, говоря PHP, чтобы не использовать файлы cookie для сеансов. Настройка PHP является session.use_cookies:

ini_set('session.use_cookies', 0); # disable session cookies 
session_start(); 

По умолчанию куки включены, потому что они считаются более безопасными, то с помощью параметров URL (см Sessions and security­Docs).

(2) Наконец, у меня есть процесс рендеринга после страницы (для статистики), для которого требуется доступ на запись к сеансу. Сеанс закрыт, я не могу снова вызвать session_start(), так как он отправляет файл cookie, и для него это поздно. Это сложный процесс вычисления, поэтому я должен сделать это после отправки страницы клиенту.

Возможно, возможно сказать PHP, что cookie уже установлен, добавив его в $_COOKIE superglobal array­Docs. Я никогда не экспериментировал с ним, но если вы используете session_start(), и PHP видит, что cookie сеанса уже установлен (браузером, а не PHP, $_COOKIE представляет куки-файлы браузера), он не будет отправлять заголовки (снова), чтобы установить печенье (которое, как я понимаю, это то, что вы хотите).


Edit: Некоторые тестовый скрипт, чтобы играть с:

<?php 
header('Content-Type: text/plain;'); 

echo "Incomming Cookies:\n"; 
print_r($_COOKIE); 

// to simulate that this is a new session, the session cookie is removed 
// which makes PHP think it is a new session when invoking session_start() 
// unset($_COOKIE['PHPSESSID']); 

// run the first session 
session_start(); // creates the session cookie (as we don't have one yet) 
printf("Session %s has been started: %s\n", session_name(), session_id()); 
var_dump($_SESSION); 
$_SESSION['variable'] = isset($_SESSION['variable']) ? $_SESSION['variable']++ : 0; 
session_commit(); 

printf("Session has been closed, remaining id is: %s\n", session_id()); 

// visual confirmation that session cookie has been created 
echo "Outgoing Cookies:\n"; 
print_r(headers_list()); 

// run the second session 
ini_set('session.use_cookies', 0); # disable session cookies 
session_start(); 
printf("Second session %s has been started: %s\n", session_name(), session_id()); 
var_dump($_SESSION); 
$_SESSION['2nd-variable'] = isset($_SESSION['2nd-variable']) ? $_SESSION['2nd-variable']++ : 0; 
session_commit(); 

Вы должны вызвать его с помощью веб-браузера (и PHP сессий должны быть настроены на работу).

+0

Великий, первый решение работает 'ini_set ('session.use_cookies', 0)'. Второе решение, похоже, не имеет каких-либо эффектов (я уже пробовал это вчера), но он может быть относительно моей конфигурации php. Я потрачу еще немного времени на это второе решение. Благодаря ! – Mat

+0

Я провел несколько тестов с '$ _COOKIE'. Он действительно работает, но это будет то же самое, что использовать 'ini_set();' и с 'ini_set()' более ясно, что он делает. Я добавлю скрипт к ответу, который я использовал для воспроизведения, прокомментирован какой-то код о '$ _COOKIE'. Раскомментируйте его, чтобы сгенерировать новый идентификатор сеанса для первого сеанса. Это также показывает, как '$ _COOKIE' связано с' session_start() '. – hakre

+0

'ini_set ('session.use_cookies', '0');' отлично работает для заголовка файла cookie, но не для заголовка кэша, который истекает из файла cookie SID. См. Ответ @techdude для использования 'session_start (['use_cookies' => '0', 'cache_limiter' => '']);' – Code4R7

-3

Вы можете использовать ob_start() функции для буферизации заголовков/контента, вы можете очистить содержимое буфера с помощью ob_clean()

+4

ob_start не заголовок буфера. Только содержание тела. Так что это работает сон. – Mat

4

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

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

session_start(array(
    'use_cookies' => '0', 
    'cache_limiter' => '' 
)); 

Обратите внимание, что use_cookies держит печенье с отправкой, и установив ограничитель кэша в пустую строку сохраняет его от обновления заголовков кэша (не лучший документированная особенность).

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

Warning: session_start(): Cannot send session cookie - headers already sent 

и

Warning: session_start(): Cannot send session cache limiter - headers already sent 
+0

Это должен быть главный ответ! +1 – Code4R7

Смежные вопросы