1.connect中介軟體csrf
原理:在express框架中csrf 是通過connect 模組的中介軟體來解決的。其原理是在前端構造一個隱藏的表單域“_csrf” ,後端生成一個值,作為該表單域,然後在提交表單的時候,將這個值提交到後端,後端再根據這個值來比較,如果和之前的值相等的,就認為是正確的,否則就是錯誤的。 我們來看看程式碼:
module.exports = function csrf(options) { options = options || {}; var value = options.value || defaultValue; return function(req, res, next){ // already have one var secret = req.session._csrfSecret; if (secret) return createToken(secret); // generate secret uid(24, function(err, secret){ if (err) return next(err); req.session._csrfSecret = secret; createToken(secret); }); // generate the token function createToken(secret) { var token; // lazy-load token req.csrfToken = function csrfToken() { return token || (token = saltedToken(secret)); }; // compatibility with old middleware Object.defineProperty(req.session, '_csrf', { configurable: true, get: function() { console.warn('req.session._csrf is deprecated, use req.csrfToken() instead'); return req.csrfToken(); } }); // ignore these methods if ('GET' == req.method || 'HEAD' == req.method || 'OPTIONS' == req.method) return next(); // determine user-submitted value var val = value(req); // check if (!checkToken(val, secret)) return next(utils.error(403)); next(); } } };
我們看到,直接以function(req,res,next){} 返回,在這個函式裡面有一個 createToken 函式,就是生成token 的,將token的值直接繫結在請求物件req的屬性上,req.csrfToken = function
我們可以直接呼叫這個函式,生成值,返回給頁面,賦值給表單域。然後表單提交 經過checkToken 函式,比較是否相同,如果是就呼叫next 函式,否則直接呼叫utils.error(403) 了。
2. cookie_secret
express 可以通過connect的中介軟體模組cookieParser 來解決
使用方法:
connect() * .use(connect.cookieParser('optional secret string')) * .use(function(req, res, next){ * res.end(JSON.stringify(req.cookies)); * })
3.paypal 的lusca 模組
這個模組很簡潔,可以解決csrf,p3p,xframe,csp 等問題。使用起來很簡單。官方地址
原理: csrf 是直接呼叫express 框架的csrf來解決的,p3p和xframe ,csp 都是設定response header 來解決的。
呼叫方式為:
var express = require('express'), appsec = require('lusca'), server = express(); server.use(appsec.csrf()); server.use(appsec.csp({ /* ... */})); server.use(appsec.xframe('SAMEORIGIN')); server.use(appsec.p3p('ABCDEF'));
也可以直接這麼使用
server.use(appsec({ csrf: true, csp: { /* ... */}, xframe: 'SAMEORIGIN', p3p: 'ABCDEF' }));