python保持登录状态_“保持登录状态”-最佳方法
小編典典
好的,讓我直言不諱:如果您為此目的將用戶數(shù)據(jù)或從用戶數(shù)據(jù)派生的任何內(nèi)容放入cookie,則表示您做錯(cuò)了。
那里。我說(shuō)了?,F(xiàn)在我們可以繼續(xù)實(shí)際的答案了。
您問(wèn)哈希用戶數(shù)據(jù)有什么問(wèn)題嗎?好吧,它可歸結(jié)為暴露表面和安全性。
想象一下您是攻擊者。您會(huì)在會(huì)話中看到為“記住我”設(shè)置的加密cookie。寬度為32個(gè)字符。嘖嘖。那可能是MD5 …
我們還要想象一下,他們知道您使用的算法。例如:
md5(salt+username+ip+salt)
現(xiàn)在,攻擊者所需要做的就是強(qiáng)行加“鹽”(這實(shí)際上不是鹽,但稍后會(huì)更多),他現(xiàn)在可以使用其IP地址的任何用戶名生成他想要的所有偽造令牌!但是強(qiáng)行撒鹽很難,對(duì)嗎?絕對(duì)。但是現(xiàn)代的GPU非常擅長(zhǎng)于此。并且除非您在其中使用足夠的隨機(jī)性(使其足夠大),否則它將很快下降,并隨即成為城堡的關(guān)鍵。
簡(jiǎn)而言之,唯一保護(hù)您的是鹽,它并沒(méi)有像您想的那樣真正保護(hù)您。
可是等等!
所有這些都假定攻擊者知道該算法!如果這是秘密且令人困惑,那么您就安全了,對(duì)嗎? 錯(cuò)誤 。這種思路有一個(gè)名字:“ 通過(guò)模糊實(shí)現(xiàn)安全” ,
永遠(yuǎn)不要 依賴它。
更好的方法
更好的方法是永遠(yuǎn)不要讓用戶的信息離開(kāi)服務(wù)器,除了ID。
用戶登錄時(shí),生成一個(gè)大的(128至256位)隨機(jī)令牌。將其添加到將令牌映射到用戶標(biāo)識(shí)的數(shù)據(jù)庫(kù)表中,然后將其發(fā)送到cookie中的客戶端。
如果攻擊者猜測(cè)另一個(gè)用戶的隨機(jī)令牌怎么辦?
好吧,讓我們?cè)谶@里做一些數(shù)學(xué)運(yùn)算。我們正在生成一個(gè)128位隨機(jī)令牌。這意味著有:
possibilities = 2^128
possibilities = 3.4 * 10^38
現(xiàn)在,為了展示這個(gè)數(shù)字有多么荒謬,讓我們想象一下互聯(lián)網(wǎng)上的每臺(tái)服務(wù)器(今天的數(shù)字是5000萬(wàn))試圖以每秒10億的速度暴力破解該數(shù)字。實(shí)際上,您的服務(wù)器會(huì)在這樣的負(fù)載下融化,但讓我們來(lái)解決這個(gè)問(wèn)題。
guesses_per_second = servers * guesses
guesses_per_second = 50,000,000 * 1,000,000,000
guesses_per_second = 50,000,000,000,000,000
因此,每秒50萬(wàn)億次猜測(cè)。快!對(duì)?
time_to_guess = possibilities / guesses_per_second
time_to_guess = 3.4e38 / 50,000,000,000,000,000
time_to_guess = 6,800,000,000,000,000,000,000
6.8秒
讓我們嘗試將其歸結(jié)為更友好的數(shù)字。
215,626,585,489,599 years
甚至更好:
47917 times the age of the universe
是的,這是宇宙年齡的47917倍…
基本上,它不會(huì)被破解。
所以總結(jié)一下:
我建議的更好的方法是將cookie分為三個(gè)部分存儲(chǔ)。
function onLogin($user) {
$token = GenerateRandomToken(); // generate a token, should be 128 - 256 bit
storeTokenForUser($user, $token);
$cookie = $user . ':' . $token;
$mac = hash_hmac('sha256', $cookie, SECRET_KEY);
$cookie .= ':' . $mac;
setcookie('rememberme', $cookie);
}
然后,進(jìn)行驗(yàn)證:
function rememberMe() {
$cookie = isset($_COOKIE['rememberme']) ? $_COOKIE['rememberme'] : '';
if ($cookie) {
list ($user, $token, $mac) = explode(':', $cookie);
if (!hash_equals(hash_hmac('sha256', $user . ':' . $token, SECRET_KEY), $mac)) {
return false;
}
$usertoken = fetchTokenByUserName($user);
if (hash_equals($usertoken, $token)) {
logUserIn($user);
}
}
}
注意:不要使用令牌或用戶和令牌的組合來(lái)查找數(shù)據(jù)庫(kù)中的記錄。始終確保根據(jù)用戶來(lái)獲取記錄,并使用時(shí)序安全比較功能隨后對(duì)獲取的令牌進(jìn)行比較。有關(guān)定時(shí)攻擊的更多信息。
現(xiàn)在, 非常
重要的一點(diǎn)是SECRET_KEY成為一個(gè)密碼秘密(由類似東西的東西生成/dev/urandom和/或從高熵輸入中得出)。另外,還GenerateRandomToken()需要成為一個(gè)強(qiáng)大的隨機(jī)源(mt_rand()還不夠強(qiáng)大。請(qǐng)使用一個(gè)庫(kù),例如RandomLib或random_compat,或mcrypt_create_iv()與一起使用DEV_URANDOM)…
這hash_equals()是為了防止定時(shí)攻擊。如果使用PHP
5.6以下的PHP版本,hash_equals()則不支持該功能。在這種情況下,您可以替換hash_equals()為timingSafeCompare函數(shù):
/**
* A timing safe equals comparison
*
* To prevent leaking length information, it is important
* that user input is always used as the second parameter.
*
* @param string $safe The internal (safe) value to be checked
* @param string $user The user submitted (unsafe) value
*
* @return boolean True if the two strings are identical.
*/
function timingSafeCompare($safe, $user) {
if (function_exists('hash_equals')) {
return hash_equals($safe, $user); // PHP 5.6
}
// Prevent issues if string length is 0
$safe .= chr(0);
$user .= chr(0);
// mbstring.func_overload can make strlen() return invalid numbers
// when operating on raw binary strings; force an 8bit charset here:
if (function_exists('mb_strlen')) {
$safeLen = mb_strlen($safe, '8bit');
$userLen = mb_strlen($user, '8bit');
} else {
$safeLen = strlen($safe);
$userLen = strlen($user);
}
// Set the result to the difference between the lengths
$result = $safeLen - $userLen;
// Note that we ALWAYS iterate over the user-supplied length
// This is to prevent leaking length information
for ($i = 0; $i < $userLen; $i++) {
// Using % here is a trick to prevent notices
// It's safe, since if the lengths are different
// $result is already non-0
$result |= (ord($safe[$i % $safeLen]) ^ ord($user[$i]));
}
// They are only identical strings if $result is exactly 0...
return $result === 0;
}
2020-05-26
總結(jié)
以上是生活随笔為你收集整理的python保持登录状态_“保持登录状态”-最佳方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python调用ffmpeg_Pytho
- 下一篇: python多线程实现同步的方式_深入解