2013-11-26 70 views
9

最近我已經注意到很多空白會話正在創建,但我不確定爲什麼,但我相信我正在以正確的方式做所有事情。通過登錄系統生成的PHP空會話文件

目前,我們創建一個會話當用戶要麼日誌中寄存器,我們再檢查用戶是否與一個isset($_COOKIE['auth'])屬於登錄或註冊過程中創建的會話登錄。

如果該cookie存在,我們開始一個會話,這有助於避免爲未註冊用戶啓動數千個會話並創建大量會話文件。

會話設置:

PHP文件

session_save_path("/home/user/sessions"); 
session_set_cookie_params("86400", "/"); 
session_name("auth"); 

的php.ini

session.gc_maxlifetime = 90000 
session.cookie_lifetime = 90000 
session.use_trans_sid = 0 
session.use_only_cookies = 1 

創建登錄會話(成功登錄)

session_start(); 
session_regenerate_id(true); 

$_SESSION['userId'] = $userId; 
$_SESSION['created'] = time(); 

session_write_close(); 
header("Location: $_SERVER[HTTP_REFERER]"); 

檢查會話是否應恢復

然後檢查是否根據是否啓動會話或不爲用戶auth會話cookie已設置。

如果用戶已經註冊或登錄之前,它只會設置:

if(isset($_COOKIE['auth'])){ 
    session_start(); 
    session_write_close(); 
} 

檢查用戶登錄

要檢查如果用戶在我們登錄然後使用功能:

function isAuthenticated(){ 

    if (!isset($_SESSION['userId'])) 
     return false; 
    else 
     return true; 
} 

註銷

function logOut(){ 
    session_start(); 
    session_destroy(); 
    setcookie('auth', "", 0); 
    unset($_SESSION); 
    unset($_COOKIE['auth']); 
    return true; 
} 

出於某種原因,雖然我獲得了大量的會話中的空文件夾(文件大小0)會議文件。

這些來自哪裏?

是否session_regenerate_id(true)創建新的會話文件並保留舊的會話文件爲空?這是我能想到空會話文件的唯一原因嗎?

+0

是的,它應該由gc更好地處理,但是如果你調用一個創建會話ID的函數,你正在創建一個會話。只要調用session_destroy,如果他們沒有通過身份驗證。 – Anthony

+1

'session.auto_start = 0'? –

+0

您應該考慮通過'foreach'將unset($ _ SESSION)'更改爲迭代,以便分別取消設置每個元素。 [PHP文檔說](http://www.php.net/manual/en/function.session-unset.php#refsect1-function.session-unset-notes):「小心:不要取消設置整個$ _SESSION與未設置($ _ SESSION),因爲這將禁止通過$ _SESSION超全局註冊會話變量。「 –

回答

0

不應該header("Location: $_SERVER[HTTP_REFERER]");需要是header("Location: $_SERVER['HTTP_REFERER']");?或者這只是一些愚蠢的東西。

編輯:

根據PHP.net你應該使用delete_old_session參數。看看HERE

+0

@André我知道,但我注意到了它。所以我告訴他... – LisaW

+0

Downvote ????????????????非常noob,這樣的白癡,哇。 +1對我來說,因爲我想給出相同的答案。你不能使用你沒有定義的常量代替字符串。除此之外,它允許頭注入並且是一個很大的安全問題。但更好地使用它是這樣的:'header(「Location:」。$ _SERVER ['HTTP_REFERER']);' – DanFromGermany

+0

我設置了一個演示爲什麼這個答案很重要:http://blog.flowl.info/2014/cant- put-array-variables-right-string/ – DanFromGermany

2
bool session_regenerate_id([bool $delete_old_session = false]); 

查看php manual瞭解更多信息。

session_regenerate_id()將用新的會話id替換當前會話id,並保留當前會話信息。

保留舊的會話文件並在每次運行session_register_id()時生成新的會話文件。 session_register_id()用新的session_id創建一個新的會話,但保留舊的會話信息,所以是的,你的session_register_id()在將信息更新到新的會話文件後保持舊的會話文件爲空。

+0

正如您在手冊中所看到的,將true傳遞給此函數將刪除舊的會話文件。 – Mahoor13

0

只需我2美分:一個用戶(無論是否登錄)在某段時間內使用該網站,通常稱爲「會話」。總是開始一個會話並保留一個會話變量來查看是否有人被認證是否會成爲問題。現在看起來你試圖只在某人登錄時纔開始會話,這會增加更多的開銷,而不僅僅是開始一個會話並檢查一個變量是否具有相同的行爲。

如果您保持會話超時低,有人會自動註銷。根據網站流量,您可以將GC設置爲更頻繁或更不頻繁。 (請參閱:http://www.php.net/manual/en/session.configuration.php#ini.session.gc-divisor

如果硬盤是會話的瓶頸(太多empy會話文件等),請創建一個小RAMdisk來存儲會話信息。

1

session_regenerate_id(true)是否會創建一個新的會話文件並將 舊的會話文件留空?這是我能想到 空會話文件的唯一原因嗎?

調用session_regenerate_id(true)試圖刪除會話文件,但如果它失敗了,將返回false(請參閱下面的相關php源代碼)。出於這個原因,我建議您驗證會話功能的成功運行,即

if(!session_start()) { 
    //log error 
} 

if(!session_regenerate_id(true)) { 
    //log error 
} 

還要檢查你爲你的垃圾收集器的頻率運行設置。也許它運行的概率很低,而且你看到孤立的會話積累。下面的設置將在每次運行php時以1/100(1%)的概率運行垃圾回收器。嘗試刪除所有孤兒,方法是將兩個值都設置爲1,然後將值設置爲1/100,如下所示。

session.gc_probability = 1 
session.gc_divisor = 100 

最後,您的註銷方法會在瀏覽器關閉時過期會話cookie。嘗試呼叫立即到期的它,而不是

setcookie('auth', null, -1); 

PHP源動力session_regenerate_id

https://github.com/php/php-src/blob/master/ext/session/session.c

注到PS(mod)->s_destroy(&PS(mod_data), PS(id) TSRMLS_CC)

/* {{{ proto bool session_regenerate_id([bool delete_old_session]) 
    Update the current session id with a newly generated one. If delete_old_session is set to true, remove the old session. */ 
static PHP_FUNCTION(session_regenerate_id) 
{ 
    zend_bool del_ses = 0; 

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &del_ses) == FAILURE) { 
     return; 
    } 

    if (SG(headers_sent) && PS(use_cookies)) { 
     php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot regenerate session id - headers already sent"); 
     RETURN_FALSE; 
    } 

    if (PS(session_status) == php_session_active) { 
     if (PS(id)) { 
      if (del_ses && PS(mod)->s_destroy(&PS(mod_data), PS(id) TSRMLS_CC) == FAILURE) { 
       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session object destruction failed"); 
       RETURN_FALSE; 
      } 
      efree(PS(id)); 
      PS(id) = NULL; 
     } 

     PS(id) = PS(mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC); 
     if (PS(id)) { 
      PS(send_cookie) = 1; 
      php_session_reset_id(TSRMLS_C); 
      RETURN_TRUE; 
     } else { 
      PS(id) = STR_EMPTY_ALLOC(); 
     } 
    } 
    RETURN_FALSE; 
} 

PS_DESTROY_FUNC

https://github.com/php/php-src/blob/master/ext/session/mod_files.c

VCWD_UNLINK這是一個命令,以從磁盤中刪除該文件。

PS_DESTROY_FUNC(files) 
{ 
    char buf[MAXPATHLEN]; 
    PS_FILES_DATA; 

    if (!ps_files_path_create(buf, sizeof(buf), data, key)) { 
     return FAILURE; 
    } 

    if (data->fd != -1) { 
     ps_files_close(data); 

     if (VCWD_UNLINK(buf) == -1) { 
      /* This is a little safety check for instances when we are dealing with a regenerated session 
      * that was not yet written to disk. */ 
      if (!VCWD_ACCESS(buf, F_OK)) { 
       return FAILURE; 
      } 
     } 
    } 

    return SUCCESS; 
}