亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

PHP登錄安全實(shí)戰(zhàn):TOTP多因素認(rèn)證、風(fēng)控?cái)r截與Redis會(huì)話一致性

PHP登錄安全實(shí)戰(zhàn):TOTP多因素認(rèn)證、風(fēng)控?cái)r截與Redis會(huì)話一致性 前陣子接手一個(gè)老 PHP 電商項(xiàng)目老板讓我把登錄安全做扎實(shí)。當(dāng)時(shí)我對(duì)多因素認(rèn)證、風(fēng)控?cái)r截、會(huì)話一致性這三塊也只是有個(gè)大概認(rèn)知網(wǎng)上現(xiàn)成的庫(kù)又不敢直接塞進(jìn)生產(chǎn)環(huán)境干脆從零開(kāi)始寫一套。正好手上有個(gè) PHP 8.3 的空閑服務(wù)配合 Redis 直接把整條認(rèn)證鏈路捋了一遍。這篇文章就用“庖丁解?!钡姆绞桨训卿涹w系拆成三塊骨頭——多因素認(rèn)證怎么做、風(fēng)控?cái)r截怎么評(píng)分、會(huì)話一致性怎么保證——每一塊我都會(huì)給代碼、給思路、給踩坑記錄。內(nèi)容偏實(shí)操適合那些有 PHP 基礎(chǔ)、但還沒(méi)完整構(gòu)建過(guò)認(rèn)證體系的開(kāi)發(fā)者看完可以直接照著落地也能理解每個(gè)設(shè)計(jì)決策背后的原因。1. 項(xiàng)目解牛三個(gè)模塊為什么必須放一起做很多人會(huì)把“多因素認(rèn)證”“風(fēng)控?cái)r截”“會(huì)話一致性”當(dāng)成三個(gè)獨(dú)立需求分開(kāi)做這是非常容易踩坑的地方。用戶的登錄行為是一條完整鏈路三者的關(guān)系是前后串聯(lián)的請(qǐng)求先進(jìn)入風(fēng)控引擎風(fēng)控決定你要不要做二次認(rèn)證二次認(rèn)證通過(guò)之后再建立會(huì)話。拆開(kāi)做最終聯(lián)調(diào)時(shí)一定會(huì)出現(xiàn)接口對(duì)不齊、狀態(tài)不同步的問(wèn)題。所以從設(shè)計(jì)第一天起就要把它們當(dāng)成一個(gè)閉環(huán)看。1.1 先捋清楚需求的三條主線多因素認(rèn)證解決的是“密碼泄露”問(wèn)題。就算用戶的賬號(hào)密碼被釣魚、撞庫(kù)撞出來(lái)了沒(méi)有第二個(gè)因素攻擊者依然進(jìn)不來(lái)。我這邊選了 TOTP基于時(shí)間的一次性密碼作為主認(rèn)證方式因?yàn)樵跊](méi)有服務(wù)商依賴的前提下它完全離線可用客戶不用等短信也不會(huì)被通道延遲坑。風(fēng)控?cái)r截解決的是“碰撞與自動(dòng)化攻擊”問(wèn)題。密碼錯(cuò)誤 100 次和密碼錯(cuò)誤 1 次兩者風(fēng)險(xiǎn)完全不一樣。風(fēng)控引擎就是在正式認(rèn)證前給這次請(qǐng)求打分分?jǐn)?shù)決定走什么處置策略。它的價(jià)值不僅在于防黑客還能防止正常用戶被暴力破解影響。會(huì)話一致性解決的是“登錄態(tài)在多機(jī)、多端下的漂移”問(wèn)題。生產(chǎn)環(huán)境至少兩臺(tái) Web 服務(wù)器如果 Session 存在本地文件里負(fù)載均衡一轉(zhuǎn)發(fā)用戶就被“強(qiáng)制下線”了。把 Session 搬到 Redis 之后不管請(qǐng)求打到哪臺(tái)機(jī)器都能讀到同一份登錄數(shù)據(jù)。1.2 技術(shù)選型與目錄結(jié)構(gòu)我全程用的是 PHP 8.3 Redis 7 nginx路由自己寫不依賴重型框架。核心邏輯全部用原生 PHP 實(shí)現(xiàn)二維碼生成用endroid/qr-code其他的能省則省。為什么要刻意去掉框架因?yàn)榭蚣艿姆庋b會(huì)把很多關(guān)鍵機(jī)制藏起來(lái)比如 Session 生命周期、Cookie 屬性、序列化方式這些恰恰是登錄體系最容易出問(wèn)題的地方。用原生實(shí)現(xiàn)一遍你能清楚看到每一步發(fā)生了什么。項(xiàng)目目錄結(jié)構(gòu)大致長(zhǎng)這樣auth-system/ ├─ public/ │ └─ index.php ├─ app/ │ ├─ Auth/ │ │ ├─ Totp.php │ │ ├─ OneTimeCode.php │ │ ├─ RiskEngine.php │ │ └─ SessionManager.php │ ├─ Support/ │ │ ├─ Base32.php │ │ └─ RedisClient.php │ └─ Config.php ├─ composer.json └─ .env每個(gè)類的職責(zé)很純粹Totp處理時(shí)間同步驗(yàn)證碼OneTimeCode負(fù)責(zé)短信/郵件驗(yàn)證碼和備份碼RiskEngine做信號(hào)采集和風(fēng)險(xiǎn)評(píng)分SessionManager統(tǒng)一接管 Redis 里的會(huì)話讀寫。這種職責(zé)劃分也方便以后替換實(shí)現(xiàn)比如風(fēng)控規(guī)則想升級(jí)成機(jī)器學(xué)習(xí)打分只需要改RiskEngine內(nèi)部邏輯。1.3 一次登錄請(qǐng)求的完整生命周期把流程在腦子里過(guò)一遍后面所有代碼都是給這個(gè)流程服務(wù)的用戶提交賬號(hào)密碼服務(wù)端先校驗(yàn)賬號(hào)是否存在、密碼哈希是否匹配。密碼校驗(yàn)通過(guò)后立刻進(jìn)入風(fēng)控引擎。風(fēng)控會(huì)采集當(dāng)前設(shè)備的指紋、IP 地理位置、User-Agent、歷史失敗次數(shù)等信號(hào)。風(fēng)控引擎輸出風(fēng)險(xiǎn)評(píng)分。0 到 35 分直接放行35 到 70 分要求二次認(rèn)證70 分以上直接拒絕。如果需要二次認(rèn)證就觸發(fā) TOTP 或短信驗(yàn)證碼流程用戶提交一次性驗(yàn)證碼。認(rèn)證通過(guò)后調(diào)用session_regenerate_id(true)重建會(huì)話把用戶身份和登錄時(shí)間寫入 Redis并下發(fā) Cookie。用戶后續(xù)請(qǐng)求會(huì)帶著 Session IDRedis 里讀出來(lái)校驗(yàn)是否過(guò)期、是否被強(qiáng)制下線然后做滑動(dòng)續(xù)期。這個(gè)鏈路里風(fēng)控在認(rèn)證之前認(rèn)證在會(huì)話建立之前。順序不能反——如果先建會(huì)話再做風(fēng)控風(fēng)控一旦把用戶攔截會(huì)話狀態(tài)就會(huì)出現(xiàn)半登錄半匿名的尷尬局面。2. 多因素認(rèn)證從 TOTP 到驗(yàn)證碼的完整鏈路多因素認(rèn)證這塊我推薦優(yōu)先做 TOTP。它不依賴短信通道用戶裝一個(gè) Google Authenticator、Microsoft Authenticator 或者 1Password 就能用。TOTP 的完整落地包含四個(gè)部分核心算法、密鑰綁定、校驗(yàn)邏輯、兜底方案。下面逐個(gè)拆。2.1 TOTP 的核心算法HMAC 與時(shí)間窗口TOTP 的本質(zhì)不是加密而是“用時(shí)間和密鑰計(jì)算一個(gè)動(dòng)態(tài)短碼”。它的底層是 HOTPHMAC-Based One-Time Password區(qū)別只在于 HOTP 把計(jì)數(shù)器傳進(jìn)去TOTP 把當(dāng)前時(shí)間戳整除 30 得到的結(jié)果當(dāng)作計(jì)數(shù)器。為什么是 30 秒這是 RFC 6238 推薦的默認(rèn)時(shí)間步長(zhǎng)太長(zhǎng)用戶等得煩躁太短用戶輸入時(shí)間不夠。核心計(jì)算代碼我用 PHP 實(shí)現(xiàn)關(guān)鍵點(diǎn)都注釋了final class Totp { public const STEP 30; public function __construct( private readonly string $secret, // base32 解碼后的原始密鑰字節(jié) private readonly int $digits 6, private readonly int $window 1, ) {} public function codeAt(float $timestamp): string { // 當(dāng)前時(shí)間步長(zhǎng) $counter intdiv((int) floor($timestamp), self::STEP); // 計(jì)數(shù)器必須是 8 字節(jié)大端序RFC 4226 里高位補(bǔ)零 $bin pack(N2, 0, $counter); // HMAC-SHA1輸出 20 字節(jié) $hash hash_hmac(sha1, $bin, $this-secret, true); // 動(dòng)態(tài)截?cái)嗳?hash 最后一個(gè)字節(jié)的低 4 位作為偏移量 $offset ord($hash[19]) 0x0f; // 從偏移量開(kāi)始取 4 字節(jié)最高位強(qiáng)制為 0避免符號(hào)位干擾 $value ((ord($hash[$offset]) 0x7f) 24) | ((ord($hash[$offset 1]) 0xff) 16) | ((ord($hash[$offset 2]) 0xff) 8) | (ord($hash[$offset 3]) 0xff); // 取模得到 6 位數(shù)字不夠前面補(bǔ)零 return str_pad((string) ($value % 10 ** $this-digits), $this-digits, 0, STR_PAD_LEFT); } }有兩點(diǎn)我想特別說(shuō)明。第一pack(N2, 0, $counter)這種寫法專門兼容 32 位 PHP把高 32 位置零低 32 位存計(jì)數(shù)器不會(huì)因?yàn)?counter超出整型范圍而飄移。第二動(dòng)態(tài)截?cái)嗍?HOTP 規(guī)范里的固定套路不是隨便取的 4 字節(jié)它保證了就算 HMAC 的某些位被翻轉(zhuǎn)取到的偏移也不會(huì)跑出哈希邊界。2.2 密鑰生成、Base32 與掃碼綁定TOTP 的種子密鑰必須是服務(wù)端為每個(gè)用戶獨(dú)立生成的不能用固定的字符串。我用random_bytes(20)生成 160 位隨機(jī)數(shù)這個(gè)強(qiáng)度已經(jīng)超過(guò)大多數(shù)需要。生成的字節(jié)沒(méi)法直接給用戶看Google Authenticator 的掃碼解析要求密鑰必須 Base32 編碼。Base32 編碼算法不復(fù)雜只是把任意字節(jié)流按 5 位一組重新映射到 A-Z 2-7 這 32 個(gè)字符上。我提供一個(gè)可直接復(fù)用的編碼函數(shù)function base32_encode(string $data): string { $alphabet ABCDEFGHIJKLMNOPQRSTUVWXYZ234567; $binary ; foreach (str_split($data) as $char) { $binary . sprintf(%08b, ord($char)); } $result ; foreach (str_split($binary, 5) as $chunk) { $result . $alphabet[bindec(str_pad($chunk, 5, 0))]; } return $result; }同樣的校驗(yàn)的時(shí)候需要 Base32 解碼把用戶掃碼得到的字符串轉(zhuǎn)回原始密鑰字節(jié)我這里給出的解碼函數(shù)要跟編碼函數(shù)配對(duì)使用function base32_decode(string $data): string { $alphabet ABCDEFGHIJKLMNOPQRSTUVWXYZ234567; $map []; for ($i 0; $i 32; $i) { $map[$alphabet[$i]] $i; } $data strtoupper(rtrim($data, )); $binary ; foreach (str_split($data) as $char) { $binary . str_pad(decbin($map[$char] ?? 0), 5, 0, STR_PAD_LEFT); } $result ; foreach (str_split($binary, 8) as $byte) { if (strlen($byte) 8) { $result . chr(bindec($byte)); } } return $result; }綁定階段的核心是生成 otpauth URI。這個(gè) URI 是一串標(biāo)準(zhǔn)的配置文本認(rèn)證器 App 看到它就知道往哪個(gè) App 生成二維碼$secretBytes random_bytes(20); $secret base32_encode($secretBytes); $issuer MyApp; $account userexample.com; $uri sprintf( otpauth://totp/%s:%s?secret%sissuer%sdigits%dperiod%d, rawurlencode($issuer), rawurlencode($account), $secret, rawurlencode($issuer), 6, 30, ); // 然后用 endroid/qr-code 把這個(gè) $uri 生成二維碼渲染到前端配套composer require endroid/qr-code把$uri傳給二維碼庫(kù)輸出 base64 圖片。這里有一個(gè)非常容易忽略的步驟綁定只是把密鑰存進(jìn)數(shù)據(jù)庫(kù)還不夠一定要讓用戶立刻提交一次當(dāng)前驗(yàn)證碼服務(wù)端驗(yàn)證通過(guò)才算綁定完成。這個(gè)“綁定即驗(yàn)證”的設(shè)計(jì)可以防止二維碼在傳遞過(guò)程中被劫持或者用戶掃錯(cuò)碼綁定成別人的種子。2.3 校驗(yàn)邏輯容錯(cuò)、防重放與防時(shí)序攻擊校驗(yàn)的核心代碼是verify它做的事情很簡(jiǎn)單算出當(dāng)前時(shí)間窗口的驗(yàn)證碼和用戶提交的比對(duì)如果不一致就往前、往后各滑動(dòng)一個(gè)窗口再比對(duì)。為什么要有滑動(dòng)窗口因?yàn)橛脩魭叽a、打開(kāi)認(rèn)證器、手動(dòng)輸入這幾個(gè)動(dòng)作會(huì)消耗時(shí)間等提交到服務(wù)端時(shí)30 秒的時(shí)間窗口可能已經(jīng)翻篇了。public function verify(string $code, float $timestamp): bool { if (!preg_match(/^\d{ . $this-digits . }$/, $code)) { return false; } $current intdiv((int) floor($timestamp), self::STEP); for ($i -$this-window; $i $this-window; $i) { $candidate $this-codeAt(($current $i) * self::STEP); if (hash_equals($candidate, $code)) { return true; } } return false; }hash_equals不是可選項(xiàng)不能用替代。原因很簡(jiǎn)單比較字符串時(shí)只要發(fā)現(xiàn)第一個(gè)不同字符就立刻返回 false攻擊者可以通過(guò)測(cè)量響應(yīng)時(shí)間反推驗(yàn)證碼的字符hash_equals會(huì)固定比較完所有字節(jié)時(shí)序上不給攻擊者留縫隙。校驗(yàn)通過(guò)之后還有一道防線防重放。同一個(gè)驗(yàn)證碼在同一個(gè)時(shí)間窗口內(nèi)只能使用一次否則只是一個(gè)被動(dòng)截獲的驗(yàn)證碼也能反復(fù)登錄。實(shí)現(xiàn)方式是驗(yàn)證成功后把當(dāng)前時(shí)間窗口記為“已使用”寫入 Redis$replayKey mfa:totp:replay:{$userId}:{$current}; $ok $redis-set($replayKey, 1, [NX, EX self::STEP * ($this-window 1)]); if (!$ok) { throw new RuntimeException(該驗(yàn)證碼已使用請(qǐng)刷新后重試); }set命令帶上NX參數(shù)表示只有 key 不存在時(shí)才寫入。第二次使用相同窗口的驗(yàn)證碼set會(huì)返回 false說(shuō)明被重放了。EX的過(guò)期時(shí)間設(shè)為窗口前后可接受的范圍避免 Redis key 堆積。2.4 短信郵件驗(yàn)證碼與備份碼的兜底方案TOTP 雖然穩(wěn)但用戶一旦換手機(jī)就會(huì)遇到“新手機(jī)還沒(méi)綁定、舊手機(jī)不在身邊”的尷尬。所以必須提供兜底方案。第一種兜底是短信或郵件驗(yàn)證碼。它的實(shí)現(xiàn)比 TOTP 簡(jiǎn)單很多生成一個(gè) 6 位隨機(jī)數(shù)字存進(jìn) Redis 并設(shè)置 5 分鐘過(guò)期然后調(diào)用短信或郵件服務(wù)商接口發(fā)送。這里有兩個(gè)關(guān)鍵細(xì)節(jié)發(fā)送限流和一次性使用。$code (string) random_int(100000, 999999); // 60 秒內(nèi)同一賬號(hào)只能發(fā)一次 $limitKey mfa:sms:limit:{$userId}; if (!$redis-set($limitKey, 1, [NX, EX 60])) { throw new RuntimeException(發(fā)送太頻繁請(qǐng)稍后再試); } $redis-setex(mfa:sms:code:{$userId}, 300, password_hash($code, PASSWORD_BCRYPT)); // $smsProvider-send($user-phone, $code);為什么要對(duì)同一個(gè)賬號(hào)限制發(fā)送頻率因?yàn)槎绦磐ǖ酪ㄥX攻擊者可以利用接口無(wú)限轟炸既浪費(fèi)成本又可能把運(yùn)營(yíng)商的通道封掉。為什么要用password_hash存驗(yàn)證碼而不是明文因?yàn)?Redis 里可能有過(guò)期數(shù)據(jù)被 dump 的風(fēng)險(xiǎn)任何時(shí)候都不要把明文驗(yàn)證碼留在存儲(chǔ)層。第二種兜底是備份碼。備份碼的生成邏輯是生成 10 到 20 個(gè)隨機(jī)碼展示給用戶一次數(shù)據(jù)庫(kù)里只存每個(gè)備份碼的哈希。為什么不能存明文備份碼的殺傷力和密碼等同數(shù)據(jù)庫(kù)一旦泄露明文備份碼就直接白給。驗(yàn)證的時(shí)候把用戶輸入的備份碼哈希之后比對(duì)匹配成功就從庫(kù)里刪除這條記錄保證只能用一次。3. 風(fēng)控?cái)r截采集信號(hào)、計(jì)算風(fēng)險(xiǎn)、分級(jí)處置風(fēng)控引擎的定位是“認(rèn)證之前的一道閘門”。它不關(guān)心用戶密碼對(duì)不對(duì)它只判斷這次請(qǐng)求本身是否可疑。我從三個(gè)層面來(lái)拆信號(hào)怎么采集、分?jǐn)?shù)怎么算、觸發(fā)之后怎么處置。3.1 信號(hào)采集設(shè)備指紋、IP 情報(bào)與行為數(shù)據(jù)設(shè)備指紋是風(fēng)控最基礎(chǔ)的數(shù)據(jù)源。前端頁(yè)面加載時(shí)采集瀏覽器信息包括 User-Agent、語(yǔ)言、時(shí)區(qū)、屏幕分辨率、canvas 渲染結(jié)果、已安裝字體等然后用 SHA-256 把這些信息拼起來(lái)做一次哈希得到一個(gè)設(shè)備指紋。代碼示意如下// 前端采集后通過(guò)接口上報(bào) $deviceSignals [ ua $_SERVER[HTTP_USER_AGENT] ?? , lang $_SERVER[HTTP_ACCEPT_LANGUAGE] ?? , screen 1920x1080, timezone -480, canvas hash-string-from-canvas, ]; $fingerprint hash(sha256, json_encode($deviceSignals));但要注意這個(gè) fingerprint 是客戶端算出來(lái)傳給服務(wù)端的理論上可以被偽造。所以不能直接把這個(gè)哈希當(dāng)成身份憑證。更嚴(yán)謹(jǐn)?shù)淖龇ㄊ欠?wù)端用 HMAC 密鑰對(duì)它簽發(fā)一個(gè)設(shè)備 ID后續(xù)請(qǐng)求都帶著這個(gè)簽名后的設(shè)備 ID 關(guān)聯(lián)用戶。IP 側(cè)的情報(bào)可以通過(guò) GeoIP 庫(kù)拿到國(guó)家、城市、經(jīng)緯度。比如 GeoLite2 離線庫(kù)就可以。為什么不在這里拋具體服務(wù)商因?yàn)樯a(chǎn)環(huán)境可能用云廠商的安全產(chǎn)品也可能內(nèi)網(wǎng)部署離線庫(kù)只要最終能給一個(gè) 0 到 100 的 IP 風(fēng)險(xiǎn)分就行。行為數(shù)據(jù)是最容易獲得也最誠(chéng)實(shí)的。密碼錯(cuò)誤次數(shù)、驗(yàn)證碼錯(cuò)誤次數(shù)、同一 IP 的登錄頻率、請(qǐng)求路徑異常程度這些數(shù)據(jù)通過(guò) Redis 計(jì)數(shù)指標(biāo)就能拿到。它們的價(jià)值在于反映“趨勢(shì)”單個(gè)錯(cuò)誤可能是手滑短時(shí)間內(nèi) 20 次錯(cuò)誤就是自動(dòng)化腳本在跑。3.2 風(fēng)險(xiǎn)評(píng)分模型規(guī)則加權(quán)而不是玄學(xué)第一版風(fēng)控不需要上機(jī)器學(xué)習(xí)規(guī)則加權(quán)就夠了。原因有兩條一是新業(yè)務(wù)根本沒(méi)有歷史標(biāo)注數(shù)據(jù)供模型訓(xùn)練二是規(guī)則引擎可解釋、可調(diào)試客戶投訴“為什么被攔截”時(shí)你能立刻給出原因。我這里擬定了一套評(píng)分規(guī)則信號(hào)評(píng)分區(qū)間說(shuō)明IP 基礎(chǔ)風(fēng)險(xiǎn)0-30GeoIP 識(shí)別為 IDC、代理則高分設(shè)備新度0-25該賬號(hào)歷史從未出現(xiàn)過(guò)此設(shè)備指紋失敗次數(shù)0-25最近 10 分鐘密碼失敗次數(shù)每次 5上限 25地理位置跳躍0-20上次登錄城市與本次距離超過(guò) 500 公里訪問(wèn)軌跡異常0-15UA 異常、請(qǐng)求路徑不符合登錄流程黑名單100命中已知黑名單直接攔截需要聲明的是這個(gè)權(quán)重表是“基于常見(jiàn)實(shí)踐的配置范例”你可以按照業(yè)務(wù)特征調(diào)整但調(diào)的時(shí)候要關(guān)注每種規(guī)則誤傷多少正常用戶。核心代碼就非常直白final class RiskEngine { public function evaluate(array $signals): RiskResult { $score 0; $score $signals[ip]-score(); $score $signals[device_new] ? 25 : 0; $score min(25, $signals[fail_count] * 5); $score $this-geoJumpScore($signals[geo_before], $signals[geo_now]); if ($signals[ip]-isBlacklisted()) { return RiskResult::blocked(blacklist ip); } return RiskResult::scored($score); } }地理位置跳躍的計(jì)算用 Haversine 公式就可以。不要看經(jīng)緯度差大就拍大腿決定用戶很可能坐飛機(jī)出差這個(gè)信號(hào)要配合“IP 是否 IDC、本次登錄是否新設(shè)備”一起看。單獨(dú)一個(gè)維度超過(guò) 500 公里就加分是很粗的規(guī)則比較靠譜的寫法是距離大于閾值并且設(shè)備是新設(shè)備才給較高的權(quán)重。3.3 三種處置方式觀察、驗(yàn)證、阻斷評(píng)分出來(lái)后處置策略分成三檔0 到 35 分直接放行但把這次請(qǐng)求打上低風(fēng)險(xiǎn)標(biāo)簽寫日志。35 到 70 分進(jìn)入二次認(rèn)證流程要求 TOTP 或短信驗(yàn)證碼通過(guò)了再放行。70 分以上拒絕登錄提示環(huán)境異?;蚵?lián)系客服人工處理。第二檔里有一個(gè)值得注意的細(xì)節(jié)如果用戶本來(lái)就要做多因素認(rèn)證那風(fēng)控評(píng)分高時(shí)不應(yīng)該“再讓他做一次認(rèn)證”而是應(yīng)該在同一個(gè)認(rèn)證流程里提升挑戰(zhàn)難度。比如低風(fēng)險(xiǎn)時(shí)只要 TOTP中高風(fēng)險(xiǎn)時(shí)強(qiáng)制 TOTP 加備份碼確認(rèn)。這樣才能真正形成兩重防線而不是做兩遍無(wú)用功。同樣重要的是“后臺(tái)日志先行”。我給風(fēng)控引擎加了一個(gè)影子模式所有評(píng)分結(jié)果都記錄到日志表但初期不實(shí)際攔截。上線跑兩周之后把誤報(bào)和漏報(bào)的案例抽出來(lái)調(diào)權(quán)重再逐步開(kāi)啟攔截。風(fēng)控系統(tǒng)翻車的重災(zāi)區(qū)不是技術(shù)不夠而是規(guī)則直接拍死了正常用戶還渾然不覺(jué)。3.4 用 Redis 做滑動(dòng)窗口計(jì)數(shù)滑動(dòng)窗口計(jì)數(shù)的核心是“統(tǒng)計(jì)最近 N 秒內(nèi)的事件數(shù)量”。我舉個(gè)密碼失敗次數(shù)的例子。初始密碼校驗(yàn)失敗時(shí)執(zhí)行$failKey risk:fail:{$userId}:{$ip}; $count $redis-incr($failKey); // 注意只有第一次累加時(shí)才設(shè)置過(guò)期時(shí)間 if ($count 1) { $redis-expire($failKey, 600); }關(guān)鍵坑就在if ($count 1)這一句。如果我在每次累加之后都無(wú)腦執(zhí)行expire($failKey, 600)那么持續(xù) 10 分鐘內(nèi)每產(chǎn)生一次失敗key 的過(guò)期時(shí)間都會(huì)往后順延 10 分鐘這個(gè)“滑動(dòng)窗口”就永遠(yuǎn)滑不到頭了。只有當(dāng) key 是新建的時(shí)候設(shè)置過(guò)期才能保證 10 分鐘不動(dòng)之后窗口自動(dòng)清零。另一個(gè)常用場(chǎng)景是 IP 登錄頻率限流每分鐘最多 20 次登錄嘗試$loginKey risk:login:{$ip}; $count $redis-incr($loginKey); if ($count 1) { $redis-expire($loginKey, 60); } if ($count 20) { throw new RuntimeException(嘗試過(guò)于頻繁請(qǐng)稍后再試); }這種計(jì)數(shù)方式很簡(jiǎn)單但也有并發(fā)問(wèn)題兩個(gè)請(qǐng)求同時(shí)incr可能出現(xiàn)一個(gè)進(jìn)程看到$count 1而另一個(gè)看到$count 2的競(jìng)態(tài)。好在 Redis 的INCR是原子操作設(shè)置過(guò)期時(shí)以“第一個(gè)拿到 1 的進(jìn)程”為準(zhǔn)基本夠用。如果想更嚴(yán)謹(jǐn)可以用 Lua 腳本把“累加、設(shè)置過(guò)期、判斷閾值”打包成一個(gè)原子操作執(zhí)行。4. 會(huì)話一致性登錄態(tài)在多機(jī)環(huán)境不漂移會(huì)話一致性是這一套系統(tǒng)能不能在生產(chǎn)環(huán)境扛住的關(guān)鍵。你把認(rèn)證和風(fēng)控都做好了結(jié)果用戶一刷新就掉線體驗(yàn)同樣廢掉。這一章解決的核心問(wèn)題是怎么讓所有請(qǐng)求都讀到同一個(gè)登錄態(tài)以及登錄態(tài)什么時(shí)候失效。4.1 為什么不能用默認(rèn) SessionPHP 默認(rèn)的 Session 是把數(shù)據(jù)序列化后寫到本地文件里的。單機(jī)開(kāi)發(fā)沒(méi)問(wèn)題一旦上了負(fù)載均衡請(qǐng)求被轉(zhuǎn)發(fā)到另一臺(tái)機(jī)器那邊讀不到你的 Session 文件用戶就被判定為未登錄。表現(xiàn)就是用戶明明才登錄成功下一頁(yè)又跳回登錄頁(yè)。解決辦法是把 Session 數(shù)據(jù)統(tǒng)一存到 Redis。最簡(jiǎn)單的做法是在php.ini里改配置session.save_handler redis session.save_path tcp://127.0.0.1:6379?database2這個(gè)辦法快但不夠靈活。我更喜歡在代碼里實(shí)現(xiàn)一個(gè)SessionHandlerInterface這樣能統(tǒng)一控制 key 前綴、過(guò)期時(shí)間并且方便在強(qiáng)制下線時(shí)精準(zhǔn)刪除指定會(huì)話。實(shí)現(xiàn)見(jiàn)下一節(jié)。4.2 自定義 Redis 會(huì)話處理器先看代碼這一段是整個(gè)會(huì)話一致性的地基final class RedisSessionHandler implements SessionHandlerInterface { public function __construct( private readonly Redis $redis, private readonly int $ttl 7200, private readonly string $prefix PHPSESSID:, ) {} public function open(string $path, string $name): bool { return true; } public function close(): bool { return true; } public function read(string $id): string|false { return $this-redis-get($this-prefix . $id) ?: ; } public function write(string $id, string $data): bool { return (bool) $this-redis-setex($this-prefix . $id, $this-ttl, $data); } public function destroy(string $id): bool { return $this-redis-del($this-prefix . $id) 0; } public function gc(int $max_lifetime): int { return 0; } }注冊(cè)方式也很簡(jiǎn)單$redis new Redis(); $redis-connect(127.0.0.1, 6379); $redis-select(2); session_set_save_handler(new RedisSessionHandler($redis, 7200), true); session_start();這里我把 TTL 設(shè)為 7200 秒也就是 2 小時(shí)。但每個(gè)會(huì)話應(yīng)該有一個(gè)“最后活躍時(shí)間”的概念不能簡(jiǎn)單地 2 小時(shí)一刀切。下一節(jié)會(huì)講滑動(dòng)續(xù)期。寫入時(shí)用setex設(shè)置過(guò)期時(shí)間Redis 會(huì)在到達(dá) TTL 后自動(dòng)刪除 key這就是絕對(duì)超時(shí)的基礎(chǔ)框架。4.3 登錄成功后的 session 重建與會(huì)話數(shù)據(jù)模型登錄成功那一刻一定要調(diào)用session_regenerate_id(true)。這個(gè)方法會(huì)生成一個(gè)新的 Session ID并把舊的 Session 內(nèi)容遷移過(guò)來(lái)同時(shí)刪掉舊 ID。這么做的目的是防 Session 固定攻擊——攻擊者把固定 Session ID 種給用戶用戶登錄成功后攻擊者就可能復(fù)用同一個(gè) ID。重建 ID 之后攻擊者手里的舊 ID 直接失效。然后是會(huì)話數(shù)據(jù)模型。很多新手會(huì)把用戶對(duì)象整個(gè)塞進(jìn)$_SESSION這是錯(cuò)的。序列化整個(gè)用戶對(duì)象不僅體積大還有可能出現(xiàn)類屬性被篡改的風(fēng)險(xiǎn)。我的做法是把最小必要數(shù)據(jù)放進(jìn)去$_SESSION[user_id] 101; $_SESSION[auth_level] mfa_verified; $_SESSION[risk] [ score 20, device_id f3a9b8..., ]; $_SESSION[login_at] time(); $_SESSION[last_seen] time();為什么last_seen要單拎出來(lái)因?yàn)榛瑒?dòng)續(xù)期邏輯要用到它。注意auth_level在這里非常有用它區(qū)分“已經(jīng)通過(guò) MFA”和“還沒(méi)通過(guò) MFA”的會(huì)話。如果風(fēng)控評(píng)分中途升高你可以只把a(bǔ)uth_level改成pending讓用戶在下次操作時(shí)重新認(rèn)證而不是直接銷毀整個(gè)會(huì)話。4.4 會(huì)話續(xù)期、超時(shí)與主動(dòng)踢人續(xù)期要解決兩個(gè)矛盾用戶希望長(zhǎng)時(shí)間不重登安全團(tuán)隊(duì)希望空閑會(huì)話盡快過(guò)期。我的方案是“絕對(duì)超時(shí) 2 小時(shí) 空閑超時(shí) 15 分鐘”。每次請(qǐng)求進(jìn)來(lái)判斷l(xiāng)ast_seen距離當(dāng)前時(shí)間是否超過(guò) 900 秒if (time() - $_SESSION[last_seen] 900) { // 有活動(dòng)續(xù)期重置 session 的 TTL $_SESSION[last_seen] time(); $handler new RedisSessionHandler($redis, 7200); $handler-write(session_id(), session_encode()); }這里千萬(wàn)注意不能每次請(qǐng)求都重置 TTL否則一個(gè)掛著不動(dòng)的瀏覽器也會(huì)因?yàn)?15 分鐘內(nèi)恰好有自動(dòng)請(qǐng)求而無(wú)限續(xù)期。續(xù)期的觸發(fā)條件必須是“用戶確實(shí)在做有效操作”比如點(diǎn)了菜單、打開(kāi)了新頁(yè)面而不是后臺(tái)定時(shí)器發(fā)的心跳。主動(dòng)踢人的實(shí)現(xiàn)要靠會(huì)話索引。登錄成功后把當(dāng)前 Session ID 加入該用戶的會(huì)話集合$activeSessionsKey session:user:{$userId}; $redis-sAdd($activeSessionsKey, session_id());強(qiáng)制下線時(shí)遍歷集合逐個(gè)刪除 Redis 里的 Session keyforeach ($redis-sMembers($activeSessionsKey) as $sid) { $redis-del(PHPSESSID:{$sid}); } $redis-del($activeSessionsKey);這種設(shè)計(jì)同時(shí)支持“踢所有設(shè)備”和“只踢某臺(tái)設(shè)備”。如果業(yè)務(wù)要求同一賬號(hào)只能一個(gè)會(huì)話在線登錄成功時(shí)刪掉集合里除當(dāng)前 Session ID 之外的所有 ID 就行。要注意的是刪除 Redis 里的 Session 只是單向的攻擊者手里的 Cookie 并不會(huì)立刻消失但因?yàn)?Session 讀取不到任何數(shù)據(jù)下一次請(qǐng)求就會(huì)被判定為未登錄安全性不會(huì)受影響。5. 常見(jiàn)問(wèn)題與避坑清單這章內(nèi)容是我實(shí)際跑這套系統(tǒng)時(shí)遇到的真問(wèn)題一個(gè)一個(gè)列出來(lái)省得你再踩一遍。5.1 TOTP 時(shí)間漂移與容錯(cuò)窗口TOTP 完全不依賴網(wǎng)絡(luò)但它依賴時(shí)間。如果服務(wù)器時(shí)鐘不準(zhǔn)驗(yàn)證永遠(yuǎn)過(guò)不了。生產(chǎn)環(huán)境一定要配 NTP 同步排查時(shí)可以用timedatectl status看當(dāng)前時(shí)間偏差。用戶設(shè)備時(shí)間偏差大時(shí)我通過(guò)把window參數(shù)調(diào)到 2 解決也就是前后各允許 2 個(gè)窗口共 2.5 分鐘容錯(cuò)。但這個(gè)窗口越大重放風(fēng)險(xiǎn)越高我實(shí)際生產(chǎn)只開(kāi) 1超過(guò) 1 的讓用戶重新同步設(shè)備時(shí)間。5.2 session.save_path 與多機(jī)同步Redis 存 Session 之后多機(jī)同步最大的坑不是 Redis 本身而是 PHP 序列化格式。如果一臺(tái)服務(wù)器session.serialize_handler是php另一臺(tái)是php_binary它們寫入 Session 數(shù)據(jù)的格式就不一樣Redis 里的同一份數(shù)據(jù)可能被另一臺(tái)機(jī)器解析失敗。統(tǒng)一在每臺(tái)機(jī)器的 php.ini 里配置session.serialize_handler php session.save_handler redis然后再啟動(dòng)服務(wù)。注意 Redis key 前綴我用PHPSESSID:就是為了和默認(rèn)文件 Session 的 key 命名區(qū)分開(kāi)也方便排查時(shí)直接redis-cli查看。5.3 風(fēng)控誤殺與規(guī)則調(diào)優(yōu)風(fēng)控引擎上線頭一個(gè)月業(yè)務(wù)方天天來(lái)找我“為什么這個(gè)客服賬號(hào)登錄被擋了”。查下來(lái)基本都是誤殺。誤殺最常見(jiàn)的原因有三個(gè)代理 IP 走辦公網(wǎng)絡(luò)、用戶出差更換城市、新設(shè)備首次登錄。我的調(diào)優(yōu)方法是給規(guī)則加“影響系數(shù)”比如“設(shè)備新度”這一條只對(duì)密碼風(fēng)險(xiǎn)等級(jí)較高的賬號(hào)加成對(duì)普通用戶即使新設(shè)備也最多加 10 分而不是 25 分。早期寧可漏一點(diǎn)也不要一開(kāi)始就大殺四方。5.4 PHP 環(huán)境相關(guān)的幾個(gè)真實(shí)報(bào)錯(cuò)裝 PHP 8.3 時(shí)如果編譯 zip 擴(kuò)展容易碰到no package libzip found這通常不是 PHP 的問(wèn)題而是系統(tǒng)缺少 libzip 開(kāi)發(fā)包。CentOS 上執(zhí)行yum install libzip-develDebian 上執(zhí)行apt install libzip-dev再重新編譯就能過(guò)。Windows 下則是另一個(gè)畫風(fēng)啟動(dòng)時(shí)報(bào)vcruntime140.dll 14.0 is not compatible with PHP 8.3原因是 VC 運(yùn)行庫(kù)版本太老去微軟官網(wǎng)裝 VC 2015-2022 Redistributable 就能解決。這類環(huán)境問(wèn)題看似和認(rèn)證邏輯無(wú)關(guān)但排查起來(lái)能浪費(fèi)一整天提前寫在清單里免得大家走彎路。5.5 Cookie 和 HttpOnly 等安全屬性Session 就算放進(jìn)了 Redis如果 Cookie 能被 JS 偷偷讀走登錄態(tài)照樣不安全。我在項(xiàng)目里固定設(shè)置這幾項(xiàng)ini_set(session.use_strict_mode, 1); ini_set(session.use_only_cookies, 1); ini_set(session.cookie_httponly, 1); ini_set(session.cookie_samesite, Lax); // 線上確認(rèn) HTTPS 之后才會(huì)開(kāi)啟 ini_set(session.cookie_secure, $isHttps ? 1 : 0);use_strict_mode的作用是拒絕用戶提交的未知名 Session ID從源頭減少固定會(huì)話偽造的可能。cookie_httponly則禁止 JavaScript 讀取 CookieXSS 就算打進(jìn)來(lái)也偷不走登錄態(tài)。cookie_samesiteLax能在跨站請(qǐng)求時(shí)把 Cookie 擋在門外對(duì) CSRF 有不錯(cuò)的抑制效果。最后一條要特別小心開(kāi)發(fā)環(huán)境沒(méi)有 HTTPS 時(shí)千萬(wàn)不要把cookie_secure開(kāi)成 1否則 Cookie 根本種不進(jìn)去你會(huì)看到“登錄成功然后立刻掉線”的詭異現(xiàn)象。把這三塊從零到一完整實(shí)現(xiàn)一遍之后最值錢的東西不是哪段代碼而是你終于知道一次登錄背后到底發(fā)生了什么風(fēng)控打分、TOTP 校驗(yàn)、會(huì)話重建、Redis 里 key 的增刪改查每一步都有明確的存在理由。以后再看任何現(xiàn)成的登錄 SDK 或者框架內(nèi)置的 auth 模塊你不會(huì)再有一層黑盒恐懼反而能一眼判斷出它設(shè)計(jì)的優(yōu)劣。最后再分享一個(gè)小技巧這套系統(tǒng)的調(diào)試階段一定要在 Redis 里給 session、風(fēng)控計(jì)數(shù)、MFA 狀態(tài)分別指定不同的 database 或 key 前綴比如PHPSESSID:、risk:、mfa:。這樣線上出了故障你能直接redis-cli看一個(gè) key 的 TTL 和內(nèi)容不需要在 PHP 代碼里打斷點(diǎn)翻哪臺(tái)機(jī)器的日志。我自己這回就是這么救回一次線上大事故的。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
色色色综合网| 丝袜综合| 思思热久久成人| 久久久久久久久久久久欧美日| 中文久久爆乳| 日人妻视频91| 国产精品99精品视频网站| 区自美91| 伊人操操| 天堂蜜桃无码视频一区二区| 国产三区免费在线观看| 亚洲成人久久美女| 日韩精品一区二区日韩| 尤物视频视频官网| 密臀视频三区免费网站| 99re欧美| 酒色综合网| 日本久久久久久久久久| 97超碰超碰| 91在线国产后入风骚翘臀美女素人| 国产怡红院| 免费看久久久性性| 日本色色色色色视频| 亚洲精品无码成人久久久99| 成人无遮挡毛片免费看| 日韩熟女无码| 秋霞一集毛片观看| 国产家庭乱伦表演| 超碰精品国产无码| 美女裸体无遮挡永久免费观看网站| 超碰吊日色| 久久9久久| 免看60秒涩涩视频| 偷拍亚洲视频一区二区三区四区| 精品女同一区二区三区| 欧美翘臀视频网站一区二区三区| 亚洲影视综合| 五月天婷婷在线看 | 男女啪啪啪18禁网站| 国产久久天堂资源| 久久春色| 中文字幕日韩专区精品系列| 国产美女裸体秘 永久无遮挡| 五月天婷婷在线看| 探花一区在线| 麻豆人妻精品一区二区| 日韩精品电影| 男人女人18禁片免费看网站| 国产一区在线免费播放| 天堂8在线新版官网| 性爱乱伦网址| 人人色97| 欧美淫乱视频| 探花视频免费观看国产专区| 欧美日韩啪啪电影| 精品毛片久久久精品毛片| 秋霞影音一区二区三区| 亚洲色久| 一区二区三区四区五区高清无码永久视频 | 午夜亚洲| 三级精品三级在线观看| 美国人人操人人操| 婷婷综合激情| 超碰天天久久79| 午夜毛片高清免费不卡| 亚洲色图A| 日韩性爱小视频| 人人操人人插人www| 国产成人www免费人成看片| 久久艹逼视频| 劲爆欧美人妖三区91| 欧美日韩久久精品爱爱| 国产黄色在线播放观看| 九九性爱网| 久久久亚洲精品电影免费看| 国产自产22区| 亚洲伊人a线观看视频| 在线国产探花| 中文字幕一区二区三四五区日日骚| 日本加勒比无码专区一二三| 一中国女人毛片水真多| 色色丁香| 久偷拍欧美日韩三区| 欧美熟妇亚洲版| 色综合91好| 欧美丰满少妇xx高潮| 天天做天天爽| 后入式999| 人妻献身系列第54部| 中文字幕高清20页视频| 偷拍盗拍亚洲色图图片| 黄色网址在线免费观看| 都市激情人妻一区二区青青操视频 | 日本裸体久久色噜噜| www.操| 午夜啊啊| 蜜臀久久99精品久久久老,,| 狠狠躁久久躁| 92午夜免费福利视频| 一区二区三区日韩欧美 | 欧美资源| 密桃99999| 欧美国产操逼| 亚洲中文一区二区三区| 精品国产一区二区三区久久久蜜臀 | 国产精品 午夜福利| 天天综合~91| 亚洲欧美综合区自拍另类| 蜜臀少妇一区二区| 美女网站91| 久久五月视频| 91制服丝袜中文字幕| 久久久精品无码亚免费| 久久草视频污视频| 久久久麻豆精品| 精品一区二区三区免费古装毛片香港三级日本三级人妇 | 日本三级日本三级99| 久久久久亚洲精品| 中文字幕精品一区二区精| 日韩AV一区二区三区三州三州| 日本媚薬中文字幕在线| 天美AV片| 欧美18老人禁| 粉嫩AV输入| 亚洲五码一区二区三区| 东京热毛片调教| 久久欧美性爱视频| 美女天天干| 欧美日韩淫加| 色网在线视频观看免费| 亚洲有码视频二区| 密臀在线免费观看| 另类 日韩 熟女| aV中文麻| 麻豆婷婷成人一二三| 91被操| 人人操天天爽| 久干9操| 人乳av| 色九月婷婷| 大香蕉中文在线| 人妻夜夜爽天天爽麻豆三区网站| 黄片qw| 超碰久在线天天做| 夜夜一区二区| 亚洲精品国产无码高清| 乱人乱色一区二区三区免费| 午夜天天碰综合视频| 十八禁av无码免费网站APP| 青草视频人妻在线观看| 97人人草| 午夜AV人气不卡| 伊人性在线视频| 人人乐大香蕉| 99国产在线 精品 视频| 97色欧洲| 大香蕉综合| 综合操逼| 八戒午夜福利理论片| 91欧美性| 国产精品久久发布| 99精品成人免费看| 亚洲无码国产精品久久| 东京热综合久久一区二区| 嗯嗯,好大,好爽,好骚 | 国产资源中文字幕在线| 色九色久| 欧美少妇高潮久久91| 91精品久久综合熟女| 日韩欧美加勒比| 亚州男人的天堂| 色人久久| 黄色视频特级毛片| 久久在线观看免费视频| 九九九国产| www.AV有限公司一区| 婷婷色婷婷| 操逼视频亚洲| 在线无码视频| 国内毛片国产欧美拍| 日本 情色 1区| 亚州Av天美传媒| 狠狠2050在线观看| 91国产大片| 天天流夜夜操| 人人爱操| 极品极品色影院| 欧美gv在线观看| 精品玖九九久| 张柏芝国产一区在线观看| 国产黑白丝在线| 亚洲污污网站| 强奸熟女一区二区三区| 久久精品天美| 日韩美女高潮喷水视频| AV中文字幕剧情1区2区3| 97精品视频免费| 亚洲。日韩。欧美| 嗯嗯,好大,好爽,好骚| 人人爱夜夜爱| 国产乱弄免费在线视频。| 亚洲天堂东京热| 婷婷久久综合久| 综合色色婷婷| 人妻激情偷乱视频一区二区三区 | 久久久久密| 爽爽淫人网| 国产成人网| 九九RE视频在线精品| 啪一啪免费视频| 欧美老妇曰批的视频| 尤物网址| 日本韩欧美在线播放a| 日本高清_区二区三区| 久久久久久国产无码精品| 亚洲制服aⅴ中文字幕| 深夜国产一区二区三区在线看| 国产成人欧美一区二区三区的国产| 亚洲国产精品成人综合| 久草网站免费在线观看| 五月综合婷婷久久网站| 另类小说五月天| 大香蕉丝袜一级片| 炮色五月| 97精品国产精品免费观看| 97在线青| 青青草中文字幕| 97日韩欧美| 国产精品久久久久久久无码AV| 蜜臀一区二区三区在线| 老子午夜伦不卡影院| 日韩无码a片| 免费看欧美美女黄色大片| 激情综合五月婷婷| 中文字幕55555| 久久久久久久久久久999| 自拍亚洲综合| 久草免费在线视频| 日韩免费高清大片在线| 天天天天操| 亚洲男人的天堂一区二区| 亚州色图欧美| 99婷婷一区二区| 亚洲精品亚洲人成在线麻豆| 超碰97资源中文字幕| 九九九九精品一区| 99色网| 欧美精品一区二区少妇免费A片 | 日本美女性生活久久久久久久| 天天插天天舔舔天天干| 超碰精品97| 国产精品高潮呻吟av久久4虎| 97在线观看播放视频| 色官网在线| 91爱综合| 国产一二三福利视频网| 国产成人99久久亚洲综合| 亚洲一本色道中文无码aV天美| 伊人久久婷婷| 伊人 俄罗斯 a v| 男人的天堂99| 老司机射| juliaann丝袜大战黑鬼| 色哟哟AⅤ| 色色色99| 玖玖综合视频| 无码精品久久久天天影视| 91校园春色长篇| 亚欧美无遮挡| 桃花色涩综合影院| 欧美日日人人天天| 色色香蕉| 天天插夜夜爽| 四虎国产精品永久在线囯在线 | 艳美熟妇先锋一二三区| 青草伊人网| 操操逼视频| 伊色综合天堂色97| 97干在线视频| www.激情| 久热最新在线杭州| 素人播放一区| 国内一区二区免费| 欧亚乱色熟一区二区三四区| 葡萄牙性视频一二区| 岛国片在线观看视频亚洲| 婷婷五月天无码| 久热精品在线国产| 加勒比日本在线| 国产精品爆乳懂色蜜乳| www老逼91| 91美女视频在线观看| 99热这里只有精品9| 欧美综合色综合| 亚洲色图欧美视频| 亚洲情欲| 人妻精品4K4K4K4K4| 亚洲学生妹高清av| 久久精品老司| 日韩 欧美 另类 人妻| 97精品97久久| 伊人女女资源在线观看| 日韩欧美~中文字| 在线国产一区二区av| 国产天天噜一噜久久久| 欧美日韩91| 久久区| 澳门成人网站久国产日韩| 麻豆久久一区二区三区| 国产精品 午夜福利| 亚洲人妻中文在线视频| 精品97久久综合| 国产女人高潮嗷嗷嗷叫小说| 久久偷偷色综合蜜桃| 中文字幕123| www男人天堂| 成人精品电影| 狠狠色噜噜狠狠狠狠狠色综合久久 | 五月天开心网| 2017av无码免费无线播| 超碰无码五月97| 在线另类| 亚洲精品一区二区精品| 欧美色97| 欧美一二在线| 亚洲欧美精品福利在线| 伊人热综合| 国产久久男人天堂| 9 9精品一区二区三区| 日日操免费视频| 中文字幕日韩情色| 日日AV加勒比| 亚洲高潮少妇| 一本一道vs波多野结衣| 97超碰站| chaopen97久久| 久久久久久亚洲精品中文字幕人妻| 伊人五月天婷婷| 91亚洲狠狠色| 超硑97精品| 亚洲黄色影视| 色色福利| 亚洲欧洲av影音| 91强热人妻| 国产精品久久久久久夜夜夜夜| 亚洲日本男人天堂网| 国产中文日韩欧美一区二区三区人妻丝袜美腿| 一起草精品人妻| 国产精品直播在线观看直播| 精品久9| 亚洲精品97中文字幕| 丁香六月婷| 日操粉逼逼| 综合激情二| 国产熟女无套内射| 亚洲久久天堂| 男人天堂网手机版婷婷| 噜噜噜久久亚洲精品色情| 欧美综合自拍成人自拍第二十页| 亚欧高清v| 操逼啊啊啊91| 亚洲日韩美国人妻| 国产不卡免费在线视频| 婷婷av在线中文字幕| 91精品国产91熟女| 大香蕉一人| 国产精品粉嫩福利在线| 欧美综合网1| av大香蕉网站| 97色诱| 午夜呻吟欧美| AV一二区| 天天弄欧美| 男人天堂久久精品| 国产少妇肉丝在线观看| 亚洲天堂区| 97综合在线| 极品极品色影院| 国产精品久久久久久久久AV大片| 国人欧美精品一区二区| 午夜一区| 99热亚洲天堂| 美腿色图| 人妻少妇三级| 亚洲极品| 欧美色另类| 伊人麻豆传媒| 久久久少妇| 麻豆久久一区二区三区| 日本一道在线播放高清| 1769一区| 精品一区二区成人| 探花一区在线| 2010男人的天堂| 亚洲色图久久成人| 97视频7| 北条麻妃性愛视频| 麻豆区久久久久亚| 欧美熟妇色| 91亚州| 日韩综合无码色欲vv| 操逼不卡中文字幕| 六十路日本| 亭亭丁香激情| 亚洲诱惑天堂| 青娱乐国产剧情av一区| 国产AV激情无码久久无码| 一级特级aaaa毛片免费观看| 色五月婷婷在线| 中美日韩毛片| 欧美图片校园春色| 色综合一本| 精品一区二区在线针对华人免费观看这里只有精品免费观看 | 人妻人久久精品中文字幕| 亚洲欧洲日韩中文字幕一区| 91久久| 中文字幕一二区二三区人妻专区| 亚洲无线码一区国产欧美国| 江都AV在线| 欧美日韩美女精品久草一区二区三区| 啊啊啊啊啊啊好多水| 亚洲国产av中文字幕久久| 最近的最新的中文字幕视频| 久久嫩草国产成人一区| 欧美午夜熟妇黑人精品91| 思思热在线视频免费| 亚洲国产高清福利视频| av婷婷色网| 就去色综合| 涩涩涩综合| 一区二区 韩日AV| 精品美女少妇一区二区三区| 超碰色综合| 国产一级αv免费看片| 一区=区三区视频| 婷婷探花久久精品一区| 精品久久无码午夜福利| 欧美亚洲综合色| 青青草一区二区三区四| 大香蕉免费3| 美女尤物福利视频| 综合色区偷拍| 插欧洲美女欧美精品| 欧美精品 - 91爱爱| 极品色综合| 秋霞蝌科网日本一区| 91精品人妻一区二区三区蜜桃臀| 欧美天天射| 色综合网1| 成人片视频| 奇米四色网| 蜜臀在线免费观看在线免费观看| 欧美碰碰综合色| 国产 丝袜 欧美中文 另类| 人妻少妇精品久久久| 国产午夜精品在线观看| 淫淫总合网| 亚洲激情视频| 久久精品国产精品亚洲艾通辽熟妇 | 天综合网| 蜜臀久久99精品久久久久久无删减 | 一道本东京热加勒比一区二区三区| 99这里只有精品| 亚洲系列第一页| 一本大道综合伊人精品热热| 波多野结衣被操50分钟免费视频| 黄色高清久久无码依人| 99久久亚洲精品无码毛片潘甜甜| 日韩中字av一区| 国产品精品自在在线午夜免费| 丝袜 亚洲 偷拍| 97网色| 999在线电影香蕉| 久夜视频| 大香蕉99热| 强奸乱伦免费网站| 啊啊啊啊啊啊啊网址在线观看| 思思热免费在线视频| 欧美在线l亚洲| 黄色免费网页无码| 天天天肏屄肏屄肏屄欧美欧美| 996热| 91精片| 大香蕉欧美伊| 免费精品人妻一区二区三| 亚洲欧洲第二视频在线观看色图| 福利视频一区二区微拍| 久久一二三四五六七八九区| 成人五月香网在线| 天天干天天燥| 欧美日韩不卡传媒| 精彩视频日韩| 91成人久久| AV色女综合| 欧美在线色图| 在线观看国产黄色| 久久精品熟女亚洲AV麻豆软件| 欧美三级免费伊人| 亚洲精品视频在线播放| 综合久久久久久久久91| 2020中文字幕在线| 91亚洲精品青草| 日本免费一级AAA大片器| 久久精品女同亚洲女同13| 午夜免费视频1000| 操逼天美3区| 中文字幕免费在线观看| 亚州成人A√| 日本性爱少妇| 先锋影音av先锋一区| 国内外毛片在线观看| 区日韩亚洲乱码av电影| 93人人操人人| 中日韩免费看男女操逼大全| 国产精品久久久久久夜夜夜夜| 五月天婷婷色色| 青娱乐欧美激情一区二区| 色亚洲欧美| 熟女中出视频| 国产精品一二三免费网站| 又粗又长又爽在线观看| 激情一区二区| 日韩毛片9| 91性生活久久久| 色婷婷视频| 377p欧洲日本亚洲大胆| 免费观看一区| 婷婷人妻激情| 久久久精品视频欧州站| 人妻熟女一区二区三区在线| 蜜桃视频精品一区二区| 婷婷丁香五月激情啪啪| 久久国内| 国产综合网站在线播放 | 欧美精品久久久久久久久88| 无码人妻精品一区二区三区99不卡| 日本道人妻久久久在线不卡色视频| 久久久熟妇熟女国产| 久久天天性久久伊人| 日本肉体xxxx裸交| 欧美视频一区二区在线| 中文字幕一区二区三区四区在线视频| 久久人妻熟女一区二区| 久久青娱乐| 亚拍在线| 超碰日韩美妻| 超碰538| 丝袜喷水在线| 国产四虎在线| 欧美日韩222| 国产不卡精品91| 亚洲欧美大| 五月综合激情网| 日本中文字幕在线电影| 国产精品久久久久av| 91精品国产高清久久久久久,亚洲成人| 67194无码不卡| 正在播放:深夜激情大战,自带黑丝袜全力输出骚穴 | 中文字幕国产精品1区| 日本福利社| 九九热免费视频| 日韩精品区二区三区不卡| 男人兔费天堂| 高潮内射在线| 久久久久ab| 久久亚码| 亚洲天堂少妇| 亚洲se91| 午夜啪| 伦激情人妻另类人妻| 国产又黄又爽又刺激久久久久久| 91深夜夜| 亚洲操人| 欧美另类色| 超碰色中文| a人欧美综合天堂麻豆| 欧美色图下一页| 欧美九一精品久久久熟妇| rivers-china.com| 综合欧美亚洲| 精品人妻中文字幕4399| 久久肏大逼| 屌色在线97视频| 麻豆天美制片厂网站视频| 午夜精品久久999热蜜桃介男人用| 女同性恋中文字幕| 蜜臀久久99精品久久久| 日韩欧美aⅴ综合网站发布| 久久一区二区三区入口| 殴美性色a级欧美| 裸体美女久久久| 久久在肏| 国产成人无码啪| 99热精品在线播放| 丝袜天堂| 97超碰超| 欧美一区二区成人一卡| 亚洲天在线| 一级人妻性爱视频| 97久久视频| 东北女人| 五月丁香激情四射| 色乱二区| 亚洲中文字幕有码视频一区二区三区| 另类视频在线| 七月婷婷综合| 欧美成va视频网站| 中文字幕日韩精品一区二区三区| 97超碰精品图片| 伊人丁香五月婷婷| 精品久久久久,69国产成人精| 国产偷人妻精品一区二区在线| 国产精品久久久久久久久久久久久久吹 | 日韩人妻有码免费视频| 熟女精品一区二区三区| 午夜久久久| 高清无码久操视频| 99这里有精品视频| 91色伦| 无码 黑人一区二区三区| 亚洲婷婷五月天| 麻豆a'v电影| 免费日韩黄片| 色综合潮| 成人国产视频在线观看| 日本天天操| 我想要啊 啊 啊| 超碰无码加勒比| 亚洲不卡不卡中文字幕不卡 | 成人精品无码| 亚洲成人av色网| 五月天日日操夜夜操| 国产强奸超碰AV| 久久超碰大香蕉| 天天干天天舔| 99国产在线绯色一区| 色五月AV| 欧美九九爱| 特色a在线上| 久久婷婷五月天| 色狠狠一区二区三区香蕉| 搡老女人老妇女AAA一VU麻豆| 黄色大片一区二区密桃丝袜| 熟妇女伦乱视频| 五月丁香色婷婷| 欧美劲爆第一页| 国内91熟女人妻丝袜天天精品视频在线 | 九热中文字幕| 国产一区96在线| 亚洲图片欧美色图| 刺激性视频黄页| 欧美高清无码免费视频高清版| 久久天天摸| 精品一区二区三区国产| 欧美天天谢综合网| 国产日韩精品人妻久久久久色欲网站 | 五月天人妻综合| 色999;丁香五月| 国产成人五月天丁香花| 麻豆天美国美国产AV| 国产精品96| 91欧美偷拍| 免费αⅴ在线观看| 天天综合,91入口| www.99视频| 曰韩人妻中文字幕在线| 艳尻美人妻| 欧美性爱中文字幕无线码| 成人天天爽| 日韩欧美国产高清视频| 97超碰美女| 久久男人网| 加勒比在线视频一区二区三区| 九一国产精品| 黄污污污污| 91久久九九精品国产综合| 欧美亚洲高清不卡| 成人短视频在线观看| 欧美日韩1234| 日日日骚女人精品| 天天天天天干夜夜夜夜夜操| 国产精品熟女一区二区三区| 青青免费在线视频一区| 九九九九97| 久久这里只精品99re66图| 国内毛片四区| 欧美韩国你懂得在线 | 自拍盗摄一区| 日本三级R| 99久久国产精品免费高潮| 青青欧美| 久草视频制服诱惑| 最新国产亚洲精品精品国产亚洲综合| 性欧美91| 国产熟妇一区二区| 欧美很很操视频| av毛片aaaaa免费看| 成人一级二级| 91夜色chaopeng| 久热婷婷| 手机在线人成免费视频| 水多多映视AV| 97伊人超碰| 青青草国产盗摄一二三区| 99精品无码| 欧美激情中文字幕另类小说| 手机午夜电影神马久久| 精品对白久久不卡| 怡红院亚洲怡春院av| 91人妻视频| 亚洲91少妇| 强奸乱亚洲| 人人摸人人添人人操| 一区二区三区国产在线播放| 综合自拍| 风月影院男女十八禁| 天天综合有色网| 日韩三级一区| 丁香色色网| 欧美黄片欧美黄片xxx| 成人无码在线超碰网| 女性91网站| 狠狠爱夜夜| 亚洲成人AB| 97操综合| 99热99re6国产在线播放| 国产精品欧美激在线| 熟女日韩| www鬼畜国产男人的天堂| 色婷婷久久| 91干熟女| 欧美亚洲中文字幕| 一级久久久久久久久久久| 久久精品中文字幕观看| 福利操逼| 日韩精品免费高清视频在线| 午夜操逼不卡| 日日日日做夜夜夜夜无码| 蜜臀AV秘一区翔田千里| 国产黄色视频久久| 思思视频免费看网站| 亚洲无码国产探花在线观看| 97色诱| 色女综合| 偷拍超碰| 欧美亚洲厕所精品偷拍91| 东北老女人的激情视频| 自拍二页| 人妻内射一区二区在线视频| 情色五月天网| 天天综合网合集91| 老熟女综合网| 91骚熟女| 免费福利视频中文字幕| 超碰在线观看av不卡| 黄色小视频日本txt| 日韩性爱网址| 91人人爽人人爽人人人,gav福利视频导航,日韩欧美亚洲国产字幕四区 | 免费在线视频97| 亚洲色宗合| 26uuu最新| 欧美 日韩 亚洲 春色| 亚洲天堂人妻熟妇视频| 免费精品福利在线观看| 一区二区三区精品黑丝白丝酒店对鸡 | 中国大陆国产高清AⅤ毛片| 久久av成人无码免费| 性做久久久久久免费观看软件| 大香网伊人久久综合| 精品无码一区二区| 精品一区二区三区四区外站| 久久久久久人| 波多野42部激情无码喷潮| 久久亚洲AV无码专区国产精品| 成人三级片无码| 国产精品交换一区二区| 色情亚洲日本成人| 精品人妻一区二区蜜桃视频| 91网站18| 思思在线免费视频| 精品久久視頻在线| 熟女一区二区三区| 熟妇女伦乱视频| 先锋激情∨在线视频播放| 操比国产| 天天综合欧美综合| 欧美后入式| 丰满美女一级毛片在线播放| 巨爆乳肉感一区二区三区竹菊影视 | 日日干日日| 亚热日本熟女| 色悠久| 黄色视频特级毛片| 韩日男人的天堂| 超碰综合97在线| 国产无码精品成人| 丁香五月天啪啪| 欧美在线55555| 九九热三级片| 97超碰总站| 欧美精品成人一区二区在线观看| www.av在线观看| 日韩激情视频| 日本一级真人黄色性爱视频| 久久九九网| 亚洲综合图片在线| 欧美一二三级精品在线| 91N欧美| 亚洲日韩狠狠撸视频| 成人性爱av| 快点操死我| 亚洲少妇在线观看| 日韩人妻无码专区| 骚逼自拍99| 中国一级操逼视频| 日han少妇无码| 欧美亚洲自拍另类人妻| 国产精品麻豆成人AV艾秋| 久超碰这里只有精品| 亚洲免费在线探花| 2000亚洲男人天堂| 一级成人性爱| 国产又大又粗又长视频在线| 日本一级真人黄色性爱视频| 亚洲欧美精品一区天堂久久 | 精品欧美А∨无码黑人大荫蒂 | 亚洲精品一区二区精品| 性欧美体内射精| 久久精品一区二区一8| 玖色AV| 亚洲久久久| 五月丁香六月激情综合| 青草精品视频一日本久久久久网站| 中文字幕精品日韩中文字幕| 久久婷婷亚洲欧| 久久91视频| 97超碰久| 欧美人妻久久精品二区三区| 久久一本大香蕉 | 亚州操逼图| 天天热精品| 大屁股xxxxx| 香蕉精品二区二区| 亚洲欧洲偷拍一区| 国产一国产一级毛片古装| 99r九九| 国产在线观看91精品一区| 亚洲精品欧洲精品| 国产操操日韩三级黄| 亚洲综合伊人| 日韩成人免费电影| 国产在线播放成人免费| 超碰97男人| 综合性视频99| 欧亚免费视频| 凹凸精品熟女在线观看| 久久中文色图| 无码av永久免费专区网站| 色偷偷综合91久久噜噜| 啊…啊…操我用力操我 | 97日视频| 国产女人91精品嗷嗷嗷嗷| 久久婷婷一区| 国内精品不卡无毒99999| 久久国产在线一区二区| 91处女视频在线观看| 亚洲黄色网址视频| 91第一页| 欧美午夜视频| 在线日韩视频| 成人无遮挡毛片免费看| 欧美性Fer办公室秘书| 操高情无码| 国产欧美黑人丰满在线| 91精片| 久草资源欧美在线视频| 国产精品一级毛片不卡视| 国产乱码久久久| xxx亚洲午夜天堂| 无码日韩人妻av一| 欧州91高潮| 91丨精品丨国产丨丝袜| 亚洲色五月| 国产黄片在线免费观看| 91色宗合| 99re在线精品78| 欧美极品少妇交| 91人妻做a观看视频| 床戏久久久av一区二区麻豆| 少妇被玩视频二三区| 18禁网站在线播放| 国产精品天堂| 国产精品国产| 老熟女熟妇| 亚洲五月天激情| 亚洲人妻中文高清| 久久狠狠色噜噜狠狠狠狠97| 超碰一区二区| 97综合国产精品高潮久久| 久久久九九网站| 亚洲图片激情综合另类| 99re视频这里只有精品| 天天超级碰碰碰| 亚洲最大黄网| 婷婷色五月激情| 26uuu性| 日韩肏逼视频| 熟妇人妻一二三区免费| 精品人妻一区二区三区夜夜| 少妇免费视频| 亚洲国产精品久久久久久久久久| 懂色AV蜜臀无码精品APP| 国产又猛又粗又爽又黄| 美女诱惑一区| 久久啊啊| 老熟女阿 国产91| 啊啊啊啊啊好舒服视频| 夜夜嗷嗷一区二区| 蜜臀亚洲中文| 亚洲精品久| 长长久久免费视频| 超碰免费在线| 色啪网| 日本99热| 99热这里只有精| 午夜男女爽爽爽在线视频| 欧美综合娱乐久久| 人人看人人插| 俺去啦俺来也久久综合| 狠狠爱综合网| 国产精品美女| 亚洲综合第一页| 久久久久久久97| 91亚洲图片| 九九热精品| 啊啊啊啊免费视频| 婷婷8月天青娱乐| 秋霞欧美性爰视频| 超碰成人最新最好看| 强歼乱伦资源网| 欧美日韩操操操| 日逼国产| 性爱av在线免费观看| 少妇高潮对白在线观看| 欧美亚洲另类在线蜜桃| 一区二区三区 日韩欧美| 激情综合网五月婷婷五月天| 国产亚洲日本精品在线| 岛园激情| 六月婷婷综合| 五月婷婷综合激情| 极品色社| 色婷婷成人综合| 中文字幕十五区| 国产精品久久久九九九| 亚洲图片在线| 人妻夜爽夜夜爽| 色臀AV| 男女一进一出视频久久| 亚洲无码国产探花在线观看| 亚洲h片在线免费观看| 91快色色色色色| 91人妻PORNY九色大屁股| 操逼日韩无码| 人妻天天夜夜爽一区二区| 日韩精品人妻中文字幕有码午| 97超碰资源网| julia国产在线| 在线视频免费观看午夜| 五月婷网站| 99久久婷婷国产综合精品草原| 久久久久精| 亚洲性图91| 超碰在线91| 国内精品a| 亚洲强奸乱伦影视网| 五月天激情小说网| 青青草视频爽一爽| 五月天欧美色图| 丰满人妻一区二区三区色-百度| 自怕偷自怕亚洲精品| 99自拍视频| 人人搡人人肉久久精品| 日本 情色 1区| 色天使亚洲综合在线观看| 99热91| 熟女网站最新| 色综91| 强奸乱伦av电影| 中文字幕视频一区视频二区| 粉嫩av一区二区三区四季| 日本色日夜干| 殴美在线AⅤ| 淫色网综合| av橘色网站| 26uuu偷拍亚洲欧洲综合| 99国产人成精品| 伊人96在线| 免费一级性爱久久| 北条麻妃99精品青青久久| 9.1小视频| 午夜视频好爽啊| 久久久不能久久久久| 青青草原香蕉日本Ap| 嫩呦国产一区二区三区AV| 91ise欧美| 黄页网站成人免费| 国产成人精品无码久久| 性欧美体内射精| 天天色欧美| 伊人五月天| 色97综合中文字幕| 日本孕妇一区二区视频操逼免费看 | 成人国产二区三区在线,男女精品。| 色就色综合| 亚91亚洲网| 欧美日韩1234| 婷婷97| 97久久久久久久久久| 在线无码网站| 久久久18禁| 国产狂喷潮在线精品| 黄页大片在线观看| 亚州男人天堂| 久久久久免费少妇| 78操B| 色婷婷综合网| 97久久超碰| 3级毛片一二| 日欧操屄视频| 夜夜嗨TV| 日韩乱伦视频| 亚洲第一男人天堂| 免费av大片| 蜜桃视频啊啊啊啊| 午夜偷拍久久熟女| 日日干夜夜欢| 成人无码影片视频在线| 九九免费影片| 黄色av一区二区在线| 舔人妻中文免费视频| 综合色99| 日韩有码专区| 亚洲天堂人妻一区二区| 啊啊啊啊啊啊在线观看| 夜夜夜久久| 亚洲日韩视频二区| 久草男人天堂| 亚洲精品亚洲人成在线麻豆| 福利天天都操| 国产成人网| 欧洲在线性爱视频| 欧美日韩国产男人| 九月丁香综合网| 女人香蕉久久毛毛片精品| 丁香五月大香蕉| 亚洲天堂男人| 亚洲揄拍网| 久久一级无码精品毛片6| 精品一区二区2| 精品久久青青草| 国产精品99精品视频网站| 中文字幕伊人| 久久女婷| 沈阳熟女高潮对白视频| 在线视频一区二区传媒| 九色在线熟女国产黑人| 综合网少妇| 国产有码一区| 日韩在线观看字幕精品| 97网色| 大香蕉宅男伊人| www…国产操逼| 精品午夜福利导航| 中文字幕人乱码中文字的预防方法 | 色噜噜婷婷| 影音先锋日本乱伦| 91激情国产| 久久9精品视频| 国产久久av| 久久久久久九九九| 久久久久久久久久久久久久久久9| 国产福利影视| 亚洲精品国产精品成人| 色综合超碰超| 婷婷香蕉欧美在线一区二区三区| 日本十八禁免费看污网站| 91大香蕉伊人| 国产盗摄美女如厕大神作品在线观看 | 防屏蔽在线视频| 蜜乳av一区二区| 天天亚洲| 伊人午夜福利视频| 欧美亚男人的天堂| 久草视频分类在线| 中国一级操逼视频| 久久九色| 精品国产综合久久福利,热99这里有精品综合久久,99热这里只有免费国产精品,精 | 老熟女天天操| 欧美亚洲美少妇一区二区| 99热这里只有精| 成人黄页| 91亚洲不卡一区| 岛园激情| 强奸乱伦AV网址| 超碰97中文| #NAME?| 中文字幕精品乱码| 日本免费一区二| 色婷婷丁香五月天| 国产高清MV操逼视频| 免费精品国偷自产在线在线 | 一起草av| 伊人久久大香大香线蕉中文| 最新av中文字幕高清| 舔足天天操天天射| 97国产精选| 久久久久斤小| 色天堂综合| 99.色网| 天综合网| 99精品无码| 欧美婷婷五月天| 人人爱人人操人人性| 国产乱伦亚洲| 操逼日批| 1000部熟女视频在线观看| 999热这里只有精品| 成人开心网在线视频 | 五月天黄色激情视频| 18禁免费视频| 欧美偷拍区| 色网站导航大全| 肉动漫无遮挡h在线观看| 国产精品扒开腿做爽爽爽视频| 天天影视综合色| av天堂加勒比| 婷婷20月天青娱乐| 久久亚洲一区女同性恋中文字幕| 欧美精品亚洲精品日韩传电影| 九九九精品一区二区无码| 9久久美女首页| 亚州综合AⅤ| 日韩丝袜高跟制服在线观看| 好看的久久不射无码影视影院| 91欧美美女日韩国产婷婷| 精久久久91| 久久久九九九九| 国产情色在线| 国产精品97超碰| 国语精品av| 日韩欧美加勒比| 亚洲男人天堂网| 99婷婷一区二区| 飘花国产午夜精品不卡| 狠狠操夜夜| 丁香婷婷九月| 中文字幕一区 二区三四五 区日 日骚 | 亚洲揄拍网| 久久噜|