2014-08-30 77 views
0

非常奇怪,我希望我只是忽略了一個小細節。我已經在這條線上梳理了好幾天,但我仍然處於虧損狀態。PHP會話變量似乎自己改變

所以當我的頁面加載時,我設置了一個隨機變量爲$_SESSION['rand_token'],然後我將該值放在我的表單的隱藏字段中。當表單被提交時,我檢查會話值與帖子值,如果它們匹配,我處理表單提交,如果它們不匹配,我繼續加載頁面(這意味着表單不會被處理,會話變量再次被改變,並且隱藏的表單輸入獲得新的會話變量)。

問題是,當最後一行代碼執行到第二行代碼(第一行是session_start();執行(在表單提交後)時,會話變量有時會發生變化)我在開始時有print_r($_SESSION);和代碼的結束,看看這個

爲什麼變量變化的!?

<?php 
session_start(); 

echo '<pre>'; 
print_r($_SESSION); 
echo '</pre>'; 

if (isset($_SESSION['rand_token'], $_POST['rand_token'], $_SESSION['rand_token_expires'])) { 
    if ($_SESSION['rand_token'] == $_POST['rand_token'] && time() < $_SESSION['rand_token_expires']) { 
     //Process form 
    } else { 
     $danger_msg = 'Token Mismatch<br />Post: ' . $_POST['rand_token'] . '<br />Session: ' . $_SESSION['rand_token']; 
    } 
} 

$_SESSION['rand_token'] = md5(microtime(TRUE) . rand(0, 100000)); 
$_SESSION['rand_token_expires'] = time() + 60 * 60 * 1; 

echo '<pre>'; 
print_r($_SESSION); 
echo '</pre>'; 
?> 

<html> 
<head> 
<title></title> 
</head> 
<body> 
<form> 
    <input type="hidden" value="<?=$_SESSION['rand_token']?>" /> 
    <input type="submit" value="Submit" /> 
</form> 
</body> 
</html> 

我會照顧2名隨後提交給你的結果:

月1日的print_r:4ff3d097a6a760a4c579f8d8a5b355ed

令牌不匹配帖子:fd6bf788ed3d1393b087472f41b3efd1

令牌不匹配會話:4ff3d097a6a760a4c579f8d8a5b355ed

第二的print_r:053f22d6126130e88f355fbc5cbbde1f


1日的print_r:279a85854fc6362d8dc52b0b74d30ef7

令牌不匹配帖子:053f22d6126130e88f355fbc5cbbde1f

令牌不匹配會話:279a85854fc6362d8dc52b0b74d30ef7

第二的print_r:edbee2d6cedbf5581920af353754fed8

我知道這是一個有點混亂跟隨,但你會看到第二個print_r應該是一樣的未來第一print_r。爲什麼它在改變?!

+1

1)你可以發佈你的代碼(使用pastebin,如果它真的很大)? 2)如果您使用該帖子替換原先的帖子,您如何檢查會話的值與帖子值?這聽起來像是100%的匹配。可能是錯誤的,但我缺乏瞭解該問題的代碼。 – icecub 2014-08-30 16:18:38

+0

我認爲你已經成爲Stack的成員足夠長,知道你應該在這樣的問題中包含代碼。 – 2014-08-30 16:23:20

+0

我看不出變量是如何改變的。 難道是緩存或服務器設置/防火牆實際上是服務陳舊的令牌,而不是每次新的? – 2014-08-30 16:32:23

回答

0

這不是一個真正的答案,但是在你的代碼中有一些錯誤。我已經更新了它和它的工作完美的罰款:

<?php 
session_start(); 

echo '<pre>'; 
print_r($_SESSION); 
echo '</pre>'; 

if (isset($_SESSION['rand_token'], $_POST['rand_token'], $_SESSION['rand_token_expires'])) { 
    if ($_SESSION['rand_token'] == $_POST['rand_token'] && time() < $_SESSION['rand_token_expires']) { 
     echo "Form should be submitted."; 
    } else { 
     $danger_msg = 'Token Mismatch<br />Post: ' . $_POST['rand_token'] . '<br />Session: ' . $_SESSION['rand_token']; 
     echo $danger_msg; 
    } 
} 

$_SESSION['rand_token'] = md5(microtime(TRUE) . rand(0, 100000)); 
$_SESSION['rand_token_expires'] = time() + 60 * 60 * 1; 

echo '<pre>'; 
print_r($_SESSION); 
echo '</pre>'; 
?> 

<html> 
<head> 
<title></title> 
</head> 
<body> 
<form method="post" action=""> <!-- forgot to set form to post here, defaulted to get instead --> 
    <input type="hidden" name="rand_token" value="<?=$_SESSION['rand_token']?>" /> <!-- forgot to set name="" here --> 
    <input type="submit" value="Submit" /> 
</form> 
</body> 
</html> 
+0

在實際的代碼中,我的表單確實有方法和動作集,而隱藏的輸入確實有名稱。 如果他們沒有標記不匹配不會顯示「後」值。 – 2014-08-30 18:05:41

+0

嗯,我很樂意幫助你,但如果你測試這段代碼,它的工作方式和預期完全一樣。我無法修復沒有損壞的東西。解決問題的唯一方法是訪問您的實際代碼,我猜。 – icecub 2014-08-30 18:08:51

+0

對不起,浪費你的時間,我用PRG過程來回避這件事。 http://en.wikipedia.org/wiki/Post/Redirect/Get – 2014-08-30 18:54:33

0

我最近經歷了同樣的事情,在我的情況,特別是與時間的函數生成的令牌,如果資產之一調用 頁面返回404,它顯然再生了令牌。所以檢查頁面是否有呼叫資產返回404.