CSRF(Cross-site request forgery)是一種重要的網絡安全問題,它利用用戶已經登錄了一個網站這一情況,向該網站發送惡意請求來實施攻擊。由于JSON常用于在客戶端和服務器間傳遞數據,在JSON應用程序中防御CSRF攻擊也顯得非常重要。
要在JSON應用程序中防御CSRF,需要在客戶端和服務器端同時進行防御,客戶端可以采用如下措施:
"use strict"; function ajax(method, url, body, callback) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { callback(xhr.responseText); } }; xhr.open(method, url); xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8'); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.send(JSON.stringify(body)); }
在客戶端代碼中,這段代碼使用XMLHttpRequest對象向服務器發送JSON請求,同時設置了“Content-Type”頭和“X-Requested-With”頭。這里的“X-Requested-With”頭用于標識這個請求是AJAX請求,而不是普通的表單提交請求。這種技術被稱為”同源檢查“,因為瀏覽器將不允許從一個源發送請求到另一個源。而“X-Requested-With”頭可以幫助我們更好地檢測來源,防御CSRF攻擊。
除了在客戶端加入安全頭以外,服務器也需要進行安全防護。在服務器端編寫代碼時應該定位請求的來源是自己的站點還是跨站請求。可以通過如下代碼實現:
app.use(cookieParser()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(function(req, res, next) { res.header('X-Frame-Options', 'DENY'); res.header('X-Content-Type-Options', 'nosniff'); res.header('X-XSS-Protection', '1;mode=block'); if (req.headers.referer.indexOf('http://localhost:3000') != 0) { // 檢查referer頭 res.send({ error: 'Invalid CSRF token.' }); } else { next(); } });
上面的這段代碼是一個Node.js的中間件,其中包含了若干個安全頭,通過這些安全頭可以防范一些潛在的攻擊。以檢查referer頭為例,我們可以在服務端檢查refer頭,確認請求是否來自自己的站點。如果請求不是來自自己的站點,就必須做出適當的反應,比如發送錯誤信息或者告訴用戶重新登錄。