[英]PHP: how to flush cookies
考慮這個例子
index.php :
<script>
var first = new XMLHttpRequest();
var second = new XMLHttpRequest();
first.open('POST', 'foo.php');
second.open('POST', 'bar.php');
first.onreadystatechange = function()
{
console.log(document.cookie);
});
first.send();
second.send();
</script>
foo.php :
<?php
setcookie('foo', 'foo');
sleep(5);
bar.php :
<?php
setcookie('foo', 'bar');
當兩個請求都結束時,是否有任何方法可以在cookie中使foo == 'bar'
而不是foo == 'foo'
?
編輯:我想我需要詳細說明為什么這是一個問題。
我正在嘗試實現一個庫,以防止在我的站點上進行跨站點偽造 。 該庫要求將唯一令牌與客戶端發出的任何POST
請求一起發送。 為此,該庫將期望的令牌存儲在SESSION
,然后使用setcookie
將令牌發送到瀏覽器。
這對我來說是個問題,因為我使用的是自定義會話存儲,這是MySQL數據庫中的表。 如果兩個POST
請求在足夠短的時間內來自同一個客戶端,則會創建一個競爭條件,其中數據庫中第三個請求的期望值始終是最后一個SENT請求生成的令牌,但使用的令牌瀏覽器的請求來自於COMPLETES最后的請求。 如果請求1比請求2花費的時間更長,則cookie和數據庫與請求3不匹配。
這就是為什么我問這個特定問題。 我知道PHP中的header
立即將任何標頭信息發送到瀏覽器,而不管輸出緩沖如何,並且cookie本質上只是標頭。 那么,為什么我不能專門針對Cookie強制執行此行為?
我意識到,可以通過不發送這么近的多個請求來避免所有這些情況,但是我沒有能力在任何合理的時間內進行更改,而僅將請求排隊僅在前一個完成后發送才會負面影響對我的用戶的體驗產生很大影響。
首先,用於CSRF預防的令牌不必更改每個請求,因此我不確定為什么這是一個問題。 只需在登錄時生成令牌並堅持下去即可。
更重要的是,Cookie 不會阻止CSRF,因為Cookie也是針對偽造的請求發送的! 這不是CSRF的預防措施。 您應該將此令牌與POST數據一起發送,通常作為表單中的隱藏字段發送。
另外,默認情況下,PHP已經阻止了同一會話中的競爭條件。 如果腳本試圖session_start()
一個已經被另一個腳本使用的會話,它將休眠直到另一個調用結束或調用session_write_close()
為止。
恐怕您對原始問題的答案很簡單,不是。 您對連接沒有足夠的控制權以強制執行任何操作。 當您在編輯中編寫代碼時,cookie的設置是通過標題完成的,並且這是異步進行的。
關於您修改過的問題:您可以通過為每個客戶端存儲多個令牌來使其工作。 也就是說,每次來自客戶端的新請求都不要刪除當前令牌,而只能創建一個新令牌。 然后,客戶端不僅應發送正確的令牌,還應發送正確的“連接ID”。 該ID可以簡單地用作來自客戶端的請求數量的計數器。
另外,您可以選擇不刷新AJAX請求的令牌,而只刷新普通頁面加載的令牌。 但是,根據您網站的工作方式,這可能並不安全。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.