PHP Conference Japan 2024
新增筆記

使用者貢獻的筆記 20 個筆記

final dot wharf at gmail dot com
14 年前
由於 PHP 的 Session 控制在使用 session_set_cookie_params() 時無法正確處理 session 生命週期,我們需要採取一些措施,以便在使用者每次造訪我們的網站時變更 session 到期時間。所以,問題是這樣的。

<?php
$lifetime
=600;
session_set_cookie_params($lifetime);
session_start();
?>

當使用者返回我們的網站或重新整理頁面時,此程式碼不會變更 session 的生命週期。無論使用者請求頁面多少次,session 都將在 $lifetime 秒後過期。因此,我們只需如下覆寫 session cookie

<?php
$lifetime
=600;
session_start();
setcookie(session_name(),session_id(),time()+$lifetime);
?>

現在我們有了相同的 session cookie,且生命週期設定為正確的值。
frank at frankforte dot ca
4 年前
以下方法似乎適用於在 PHP < 7.3 的 session cookie 上設定 SameSite 屬性。

<?php

$secure
= true; // 如果您只想透過 HTTPS 接收 cookie
$httponly = true; // 防止 JavaScript 存取 session cookie
$samesite = 'lax';

if(
PHP_VERSION_ID < 70300) {
session_set_cookie_params($maxlifetime, '/; samesite='.$samesite, $_SERVER['HTTP_HOST'], $secure, $httponly);
} else {
session_set_cookie_params([
'lifetime' => $maxlifetime,
'path' => '/',
'domain' => $_SERVER['HTTP_HOST'],
'secure' => $secure,
'httponly' => $httponly,
'samesite' => $samesite
]);
}
?>
theking2(at)king.ma
1 年前
根據 PHP 7 版本,session_start 可以包含選項陣列,此函式已過時。所有 cookie 設定(以及更多設定)都可以包含在選項陣列中,作為 session_start() 的參數

<?php
session_start
( [
'cookie_path' => '/',
'cookie_lifetime' => 300,
'cookie_secure' => true,
'cookie_httponly' => true,
'cookie_samesite' => 'lax',
] );
passerbyxp at gmail dot com
12 年前
請注意,瀏覽器對於 $path 參數是區分大小寫的。

例如,如果您執行以下操作:
<?php
session_set_cookie_params
(0,"/webapp/");
session_start();
?>

然後您用以下方式瀏覽您的網站:
example.com/WebApp/

您會在每次請求時都取得一個新的 session。

我不確定這是否是標準行為,但我看到在 IE 6、Firefox 12(實際上是 Palemoon)、Chrome 19(可攜式版本),以及 IIS 和 Apache 上都會發生這種情況。
Danack dot Ackroyd at gmail dot com
13 年前
在 session_set_cookie_params() 中設定 cookie 的網域只會影響 PHP 設定的 session cookie 所使用的網域。

所有其他透過呼叫 setcookie() 函式設定的 cookie,要嘛
i) 使用在呼叫 setcookie() 時明確設定的網域
要嘛
ii) 完全不設定 cookie 的網域,因此瀏覽器會假設它是用於目前網域的。

因此,要讓您的所有 cookie 可以在您網站的所有子網域中使用,您需要這樣做:

<?php
$currentCookieParams
= session_get_cookie_params();

$rootDomain = '.example.com';

session_set_cookie_params(
$currentCookieParams["lifetime"],
$currentCookieParams["path"],
$rootDomain,
$currentCookieParams["secure"],
$currentCookieParams["httponly"]
);

session_name('mysessionname');
session_start();

setcookie($cookieName, $cookieValue, time() + 3600, '/', $rootDomain);
?>
shrockc at inhsNO dot SPAMorg
22 年前
在設定 cookie 有效的路徑時,請務必記得加上尾隨的 '/'。

正確的寫法
session_set_cookie_params (0, '/yourpath/');

不正確的寫法
session_set_cookie_params (0, '/yourpath');

我不想說我花了多久才意識到這是我驗證/session 問題的原因…
werner dot avenant at gmail dot com
12 年前
請注意像 Ubuntu 和 Debian 這樣的系統上的垃圾回收「功能」。

apt-get 會在 /etc/cron.d/php5 安裝一個 cron 指令碼,它會檢查 session.gc_maxlifetime 變數,然後每 9 和 39 分鐘刪除所有舊的 session。

問題是:如果您為特定的虛擬主機設定 maxlifetime,這些設定將被忽略。假設您希望您的伺服器只儲存 30 分鐘的 session,但對於一個特殊的網站,您希望所有 session 都是 24 小時。如果您在 .htaccess、您的 apache conf 中設定 session.gc_maxlifetime,或是在您的程式碼中使用 ini_set,它將不會起作用,session 仍然會在 30 分鐘後被銷毀。那是因為 /usr/lib/php5/maxlifetime(在該 cron 檔案中找到)總是會傳回您 php.ini 中的值,而不是您在 .htaccess 中設定的值。

一個解決方法是將 maxlifetime 設定為您網站所需的最大值,然後在您的 .htaccess 中為那些不需要它的網站設定較短的 maxlifetime。

另一個解決方案是給 /etc/cron.d 中的 php5 檔案合理的值,也就是只讓它在早上 3 點執行,但您必須記住每次更新 php 時都要阻止這個檔案被取代。
Miki
15 年前
請記住,如果您有一個多子網域的網站,您必須加入以下程式碼,才能在整個網站上啟用一個 session id:

<?php
session_set_cookie_params
(0, '/', '.example.com');
session_start();
?>

否則,您將在例如 news.example.com 和 download.example.com 上有 2 個不同的 session。
jordi at jcanals dot net
20 年前
我花了一些時間來偵錯的事情:當網域參數只是一個單層網域時,例如 TLD 時,session_set_cookie_params() 不會運作。

我有一個內部網路中的網站,我們的內部網域是 .local,因此嘗試將 cookie session 設定為 .local 網域會無效

session_set_cookie_params(0, '/', '.local'); // 無效

在我做的所有測試中,設定網域僅適用於 SLD 及以上的網域

session_set_cookie_params(0 , '/', '.sld.local'); 有效

這與 PHP 無關,而是與 http 協定有關,基於顯著的安全性考量,該協定不允許為 TLD 設定 cookie。
dan at vespernet dot co dot uk
17 年前
下面的註解是一個很好的範例,說明如何在頁面重新整理時「重設」session 的過期時間。

但是,請注意在 session 過期且無法自行續約時(我相信這是一個錯誤)進行補償。如果每次執行指令碼時都執行下面的範例,則在 session 無法續約後,它會產生「未定義索引 <session 名稱> 錯誤」。請在它之前加上 if isset() 條件。

<?php
private function startSession($time = 3600, $ses = 'MYSES') {
session_set_cookie_params($time);
session_name($ses);
session_start();

// 在頁面載入時重設過期時間
if (isset($_COOKIE[$ses]))
setcookie($ses, $_COOKIE[$ses], time() + $time, "/");
}
?>

上面的範例表示,在 session 被丟棄之前,如果沒有重新整理頁面,session 將持續一個小時。在頁面重新整理時,過期時間會再次重設為一個小時。如果您希望讓使用者可以選擇「永久保持登入狀態」,只需將 '99999999' 值提供給 startSession,這應該可以持續約 3 年。
Anonymous
16 年前
回覆 RC
>2008 年 4 月 23 日 04:45
>對於任何正在尋找哪些瀏覽器支援 HTTPOnly > 標誌的人,根據我的研究
>
>IE 6 SP 1 及更高版本。
>Firefox 3 及更高版本。
>Opera 9.50 及更高版本。

Firefox 2.0 也支援它們,但僅自 2.0.0.5 版本開始。

http://bugzilla.mozilla.org/show_bug.cgi?id=178993
theking2(at)king.ma
9 個月前
為了完全控制 session cookie,我使用這段程式碼:

<?php
session_set_cookie_params
( [
'lifetime' => 0,
'path' => '/',
'domain' => $_SERVER['HTTP_HOST'],
'samesite' => 'Strict',
] );
session_start( [
'name' => 'SESSION',
'sid_length' => 96,
'sid_bits_per_character' => 6,
'use_strict_mode' => true,
'referer_check' => $_SERVER['HTTP_HOST'],
] );
?>

這會將參數設定為建議的值,並產生一個具有合理品質的 cookie id。
eion at robbmob dot com
3 年前
不幸的是,session_set_cookie_params() 無法在作用中的 session 期間被呼叫,它只會產生 E_WARNING 並傳回 false,這表示呼叫 session_regenerate_id()(例如,在登入期間防止 session 固定攻擊)可能會最終使用舊的 cookie 設定(例如,不是 "SameSite=Strict")。

為了確保未來任何 session 都是使用正確的 cookie 設定建立的,您最好使用 ini_set() 來設定 cookie 參數 - 這也是 session_set_cookie_params() 在底層所做的。
jan at dewal dot net
14 年前
關於此函式只能在 session_start 之前使用的資訊,取決於您如何使用它。因為它在 session 開始之後也很有用,如下所示

範例:您想要變更已設定的 session cookie 過期時間值

<?php

// 這裡我們像往常一樣開始
session_set_cookie_params('3600'); // 1 小時
session_start();

// 更多程式碼...

// 現在我們在某個資料庫中發現使用者希望
// cookie 在例如 10 分鐘後過期
// 我們可以立即變更它!

session_set_cookie_params('600'); // 10 分鐘。
session_regenerate_id(true);

// 這將刪除舊的 cookie 並採用新的過期設定,並將
// 舊的 cookie 變數放入新的 cookie 中

?>

請注意,我只解釋了瀏覽器(客戶端)端對 session cookie 過期時間的變更。
gavin_spam at skypaint dot com
22 年前
session_set_cookie_params 的第一個參數是 session 將在未來(基於伺服器目前時間)過期的秒數。所以如果你想要你的 session 持續 100 天

$expireTime = 60*60*24*100; // 100 天
session_set_cookie_params($expireTime);

我之前使用 time()+$expireTime,這是錯誤的(我找到的許多 session_set_cookie_params() 範例都搞錯了,但可能不在意,因為他們只是做「無限期」的 session)。
php at mike2k dot com
23 年前
[編輯註記

來自 PHP-General 清單的 Rasmus 解決方案

只需使用 session cookie(不提供過期時間),並將
伺服器的過期時間戳記添加到 cookie 的值中。然後當你得到
傳送給你的 cookie 時,根據你伺服器的時間檢查它,並
根據該時間決定是否接受該 cookie。

這樣你就可以避免人們沒有正確設定他們的系統時鐘
的問題。

-Rasmus

--zak@php.net]

使用這個時我注意到一些事情。我認為它只在你設定 session_set_cookie_params() 函式在 session_start() 函式「之前」才有效。

另外,當你設定 cookie 的「生命週期」時,它會從「伺服器」取得秒數偏移量。它會將 cookie 編碼為在伺服器時間超時。所以如果你的伺服器比客戶端快 2 分鐘,而你設定 cookie 在 30 秒後超時,那麼客戶端實際上在 cookie 超時之前會有 2 分 30 秒。我不知道在未來版本中是否有任何方法可以修補這個問題,而且我認為唯一的替代方法是在 javascript 中設定 cookie,這在使用所有這些特定的 session 函式時根本不是重點。
William Leslie
16 年前
"Info at xyzsite dot ru" 寫道,Internet Explorer 無法正確處理網域包含底線字元的 cookie。

然而,這種明顯錯誤的行為有一個很好的理由:底線字元在 DNS 名稱中是被禁止的。RFC 3696 說

「組成網域名稱的標籤...必須僅包含 ASCII 字母和數字字元,以及連字號。不允許使用其他符號或標點符號,也不允許使用空白。」

如果底線在 Mozilla 或其他瀏覽器中有效,那只是因為它們在驗證網域名稱時比較寬鬆。
Ashus
16 年前
跨網域 Cookie 在所有瀏覽器中都有效(路徑 '/' 伺服器 '.example.com'),除非你在 IE6/7 中嘗試,且伺服器名稱是從 :etc/hosts: 檔案中擷取的,在這種情況下,cookie 甚至不會被儲存。
brandan, bildungsroman.org
16 年前
我發現使用 session 有點困難,因為文件並未真正指出必須透過 session_name() 設定 session 名稱,session_set_cookie_params() 才能使用。我在這篇文章中沒有找到任何關於 session_name() 的參考,如果不是因為一位熟悉 session 的朋友,我的 session 函式早就變得一團糟了。

所以,本質上,對於任何想知道從哪裡開始的人:在使用 session_set_cookie_params() 之前宣告 session 名稱,否則你可能會激怒 php 到對你的網路伺服器犯下一些暴行的地步。
eddie at roosenmaallen dot com
16 年前
繼 "info at xyzsite dot ru" 和 William Leslie 之後,OS X 上的 Safari 也不會接受子網域中有底線的 cookie。

我發現的解決方法是將父網域指定為 cookie 網域 -- 而不是 "bad_name.example.com",將路徑設定為 ".example.com";這並非最佳做法,但可以完成工作。
To Top