前言
- 每種后端語言都有自己的XSS/CSRF防御機(jī)制, 通常是一些類庫
Node應(yīng)用也一樣
nodejs xss 防御
-
xss.js 模塊
- NPM ----- 地址
-
后端使用方式
- 安裝方式 :
npm install xss
后端用法 : 對于用戶的輸入進(jìn)行過濾【榱健+ 數(shù)據(jù)庫取得數(shù)據(jù)進(jìn)行過濾
- 舉例 1:
let userInput = xss(req.body.userInput);
-
前端使用方式
- 安裝方式 : 頁面引入js文件, 下載地址 --- xss.js
- 前端用法 : 對于用戶的輸入遗座、調(diào)用服務(wù)取得的json 進(jìn)行過濾
- 代碼片段 舉例 1:
filterXSS('<script>alert("xss");</scr' + 'ipt>');
-
jQuery 及 基本dom操作
- 在不確定后端數(shù)據(jù)是否安全的情況下俊扳, 構(gòu)造屬性或節(jié)點時一定注意把json中的數(shù)據(jù)通過jQuery轉(zhuǎn)換為文本或文本節(jié)點
- 方式 1 :
document.createTextNode(yourDirtyString);
在給element的屬性賦值時 可以使用 - 方式 2 :
$.val(yourDirtyString)
, val方法只會將傳入的參數(shù)轉(zhuǎn)換為string 文本途蒋, 安全 - 方式 3 :
$.("<input>",{ text : yourDirtyString, value : anything here })
, 原理同上馋记, 安全
- 方式 1 :
- 在不確定后端數(shù)據(jù)是否安全的情況下俊扳, 構(gòu)造屬性或節(jié)點時一定注意把json中的數(shù)據(jù)通過jQuery轉(zhuǎn)換為文本或文本節(jié)點
nodejs csrf 防御
-
csrf 模塊
NPM ------ 地址
-
安裝方式 via npm
npm install csurf
-
使用方式
-
第一步. 前端發(fā)起get請求(get頁面)獲得token, 服務(wù)端創(chuàng)建cookie和token号坡,前端拿到token存起來 如可以放到form中的hidden input中,
注意的是 在默認(rèn)的情況下這input的id需要指定為_csrf 才能被驗證通過梯醒。只要確保發(fā)起其他post請求時 把token帶上
第二步. 前端發(fā)起增刪改查等post請求時宽堆, 帶上token傳過去, 服務(wù)端驗證cookie和token茸习, 若通過則處理請求畜隶, 否則默認(rèn)返回403.
-
-
代碼片段 expressjs(routes/someroute.js)第二步 - 服務(wù)端csrf模塊,檢驗cookie與token
var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var csrf = require('csurf'); var csrfProtection = csrf({ cookie: true }) var parseForm = bodyParser.urlencoded({ extended: false }); //從req.body(也就是parseForm)中檢驗_csrf字段的值 和服務(wù)端進(jìn)行匹配 router.post("/", parseForm, csrfProtection, function(req, res, next) { //todo }
-
代碼片段 expressjs (routes/getToken.js) 第一步:服務(wù)端csrf模塊号胚, 分配token
var express = require('express'); var router = express.Router(); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var csrf = require('csurf'); /* csrf */ var csrfProtection = csrf({ cookie: true }); var parseForm = bodyParser.urlencoded({ extended: false }); router.get("/", csrfProtection, function(req, res, next) { var token = req.csrfToken(); res.json({ "token": token }); }); module.exports = router;
-
代碼片段 前端jquery.ajax獲得token并創(chuàng)建hidden input儲存籽慢, 之后再次發(fā)起post請求
function getToken() { $.ajax({ url: config.serviceUrl + 'getToken', type: 'get', dataType: 'json', success: function(response) { if (response) { var tokenInput = $("<input>", { id: "_csrf", type: "hidden", value: response.token }); $("body").append(tokenInput); return true; } else { return false; } } }) } function deleteNews(id) { var data = { "id": id, "_csrf": $("#_csrf").val() } $.ajax({ url: config.serviceUrl + 'deleteAnything', type: 'post', data: data, dataType: 'json', success: function(response) { if (response.result === "success") { return true; } else { return false; } } }) }