? 6.1 如何防止 SQL 注入 / XSS / CSRF?
面試官您好,Web 安全三大經典問題分別從不同層面入手:
🔸 SQL 注入(Server端)
原理:惡意用戶將 SQL 注入查詢語句拼接,導致數據泄露或破壞。
防御手段:
-
使用 ORM / 預編譯語句(PreparedStatement)
-
如 Sequelize / Prisma / TypeORM 都默認使用參數化查詢
-
-
不拼接 SQL 字符串
-
堅決杜絕字符串拼接構造查詢
-
-
對用戶輸入做嚴格校驗(如白名單、正則)
? 示例(Sequelize ORM):
User.findOne({ where: { username: req.body.username } }); // 安全
🔸 XSS(跨站腳本攻擊)
原理:用戶輸入惡意腳本插入頁面,在其他用戶瀏覽時觸發執行。
防御手段:
-
前端輸出內容必須做轉義(如 DOMPurify、Vue/React 默認做)
-
后端返回的數據也可二次 HTML encode
-
設置 CSP(內容安全策略)響應頭:
Content-Security-Policy: default-src 'self'
🔸 CSRF(跨站請求偽造)
原理:攻擊者誘導用戶點擊鏈接,悄悄向另一個站點發起請求。
防御手段:
-
使用 SameSite Cookie 策略(推薦 SameSite=Strict)
-
使用 CSRF Token 校驗(如
csurf
中間件) -
對敏感操作用 POST,并驗證 Referer 頭來源
? 6.2 JWT 如何簽發與驗證?如何防止偽造?
JWT 是一種輕量的無狀態認證方案,我在 NestJS 項目中用得很多。
🧩 JWT 簽發過程:
-
用戶登錄成功后,服務端使用 私鑰(或對稱密鑰) 生成 token:
const token = jwt.sign({ uid: user.id }, SECRET_KEY, { expiresIn: '2h' });
-
客戶端將 token 存儲于:
-
安全性優先:HttpOnly Cookie
-
靈活性優先:localStorage(要防 XSS)
-
🧩 驗證 token:
后端中間件提取請求頭中的 token 并使用相同密鑰解碼:
jwt.verify(token, SECRET_KEY);
?防止偽造方法:
-
密鑰不能泄露,必須使用 非對稱加密(如 RS256) 或強對稱密鑰
-
建議使用 JWT 的 簽發者(iss)和用途(aud) 字段限制濫用
-
設置合理的過期時間(短 token + 刷新機制)
? 6.3 登錄接口如何防止暴力破解?加密算法用什么?
登錄接口是攻擊高發點,我從「加密、頻率限制、驗證碼」三方面防護:
🔒 密碼加密:
-
使用 bcrypt 加密(推薦 10 ~ 12 輪 salt):
const hash = await bcrypt.hash(password, 10);
const isMatch = await bcrypt.compare(inputPassword, hash);
-
bcrypt 是基于 Blowfish 的算法,具備慢哈希特性,抗暴力破解。
🚨 防止暴力破解:
-
IP / 用戶名 嘗試次數限制:如 5 分鐘內登錄失敗 5 次封號
-
可結合 Redis 實現計數
-
-
登錄接口接入驗證碼(如圖形驗證碼、滑動驗證)
-
接入行為分析 / 登錄地判斷(如風控中臺)
? 6.4 如何對文件上傳做安全校驗?
文件上傳是黑客最容易鉆空子的地方,需要嚴格限制上傳內容和行為。
🛡? 安全措施:
風險類型 | 對策 |
---|---|
惡意腳本文件 | 限制 MIME 類型(白名單)、校驗擴展名和真實類型 |
木馬圖片 | 使用 file-type 或 mime 判斷內容頭部 |
大文件拖垮服務器 | 限制上傳大小(如 5MB) |
路徑穿越攻擊 | 不允許用戶自定義文件路徑;統一保存在 sandbox |
文件名注入 | 生成唯一名(如 UUID),避免原始文件名沖突 |
? 示例(NestJS 文件上傳驗證):
@UseInterceptors(FileInterceptor('file', {fileFilter(req, file, cb) {const isImage = file.mimetype.startsWith('image/');cb(null, isImage);},limits: { fileSize: 5 * 1024 * 1024 }, // 限 5MB
}))
? 6.5 如何加密用戶密碼?用什么算法?
用戶密碼必須做 不可逆加密(單向散列)并加鹽。
推薦算法:bcrypt(或 argon2)
-
bcrypt 是加鹽 + 慢哈希算法(抗彩虹表 + 抗暴力破解)
-
NestJS 和 Express 項目中推薦使用
bcryptjs
或bcrypt
模塊
加密流程:
const saltRounds = 10;
const hashedPwd = await bcrypt.hash(password, saltRounds);
-
登錄時使用
compare
方法比對:
const isMatch = await bcrypt.compare(inputPassword, storedHash);
其他備選算法(了解即可):
算法 | 特點 |
---|---|
SHA256 | 不加鹽容易被反查,已不推薦 |
Argon2 | 更安全但較新,適合新系統使用 |
PBKDF2 | 可以加鹽、加輪次,銀行業常用 |
? 總結回顧
編號 | 問題 | 要點簡述 |
---|---|---|
6.1 | SQL/XSS/CSRF 防護 | ORM 防注入、DOM轉義防 XSS、CSRF Token + SameSite |
6.2 | JWT 簽發與校驗 | 簽名加密、有效期、對稱/非對稱加密、避免暴露密鑰 |
6.3 | 登錄暴破防護 | bcrypt 加密、IP 限制、驗證碼、行為識別 |
6.4 | 文件上傳安全 | 檢查 MIME 類型、文件大小、存儲路徑唯一、過濾木馬 |
6.5 | 密碼加密算法選擇 | 推薦 bcrypt / argon2,使用鹽值,嚴禁存儲明文密碼 |