我正在尝试在我的项目中实现csrf保护,但无法使其与jQuery Ajax一起使用。(不过,它适用于普通的帖子请求)
如果在发送表单之前使用chrome开发工具篡改令牌,则仍会看到“正在处理数据”文本,而不是invalid csrf token错误。
invalid csrf token
app.js
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var csrf = require('csurf'); var bodyParser = require('body-parser'); var router = express.Router(); var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); //app.set('strict routing', true); app.set('view options', {layout: false}); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: false})); app.use(cookieParser()); var csrfProtection = csrf({ cookie: true }); var parseForm = bodyParser.urlencoded({ extended: false }); app.use(express.static(path.join(__dirname, 'public'))); app.get('/form', csrfProtection, function(req, res) { // pass the csrfToken to the view res.render('send', { csrfToken: req.csrfToken() }); }); app.post('/form', parseForm, csrfProtection, function(req, res) { res.send('data is being processed'); }); // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function (err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); } // production error handler // no stacktraces leaked to user app.use(function (err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); module.exports = app;
send.jade
html head meta(name='_csrf', content='#{csrfToken}') body form(action='/form', method='POST') | Favorite color: input(type='text', class="favori", name='favoriteColor') button(type='submit') Submit script(src="javascripts/frontend/jquery/jquery-3.0.0-alpha1.js") script(src="javascripts/test.js")
test.js
$(document).ready(function () { $.ajaxSetup({ headers: {'X-CSRF-Token': $('meta[name="_csrf"]').attr('content')} }); $('button').click(function (e) { e.preventDefault(); var text = $('.favori').val(); alert(text); $.post( "/form", { text: text }, function (data) { console.log(data); }); }); });
在有效负载消息中发送CSRF令牌:
$('button').click(function (e) { e.preventDefault(); var text = $('.favori').val(); alert(text); $.post( "/form", { text: text, _csrf : $('meta[name="_csrf"]').attr('content') }, function (data) { console.log(data); }); });
为了简化您的工作,我认为您可以创建一个Jquery插件来执行此操作,如下所示:
(function( $ ) { $.postCSRF = function(to, message, callback) { message._csrf = $('meta[name="_csrf"]').attr('content'); $.post(to, message, callback); }; }( jQuery )); // Usage example: $.postCSRF('/form',{text:'hi'},function(res) { console.log(res); });
示例:http://jsfiddle.net/w7h4Lkxn/