23

express.jsフレームワークを使用してnode.jsを使用して構築されたアプリにCSRF保護を実装しようとしています。このアプリは、サーバーへのAjaxポストコールを多用します。接続フレームワークがCSRFミドルウェアを提供することは理解していますが、クライアント側のAjaxポストリクエストの範囲でそれを実装する方法がわかりません。

スタックオーバーフローでここに投稿された他の質問にこれに関する断片がありますが、クライアント側とサーバー側の両方からそれを実装する方法の合理的に完全な例をまだ見つけていません。

誰かがこれを実装する方法について共有したい実用的な例を持っていますか?私が見たほとんどの例では、サーバー側でフォームをレンダリングしてから、(埋め込まれたcsrf_tokenフォームフィールドとともに)クライアント側に送信すると想定しています。私のアプリでは、すべてのコンテンツがBackbone.jsを介してクライアント側(テンプレートを含む)でレンダリングされます。サーバーが行うのは、JSON形式で値を提供することだけです。これは、クライアント側のBackbone.jsのさまざまなモデルで使用されます。私の理解では、csrf_tokenを使用する前に、まずajaxを介して取得する必要があります。ただし、これはセキュリティの観点から問題になる可能性があるのではないかと心配しています。これは有効な懸念事項ですか?

4

5 に答える 5

33

metaCSRFトークンのタグを追加し、すべてのAjaxリクエストでCSRFトークンを渡すことで実行できます

サーバ

CSRFミドルウェアを追加

app.use(express.csrf());
app.use(function (req, res, next) {
  res.locals.token = req.session._csrf;
  next();
});

たとえば、メタタグを介して CSRF トークンをクライアント側に渡すことができます。たとえば、Jade

meta(name="csrf-token", content="#{token}")

クライアント

jQuery には ajaxPrefilter と呼ばれる機能があり、これを使用すると、Ajax リクエストごとに呼び出されるコールバックを提供できます。次に、ajaxPrefilter を使用してヘッダーを設定します。

var CSRF_HEADER = 'X-CSRF-Token';

var setCSRFToken = function (securityToken) {
  jQuery.ajaxPrefilter(function (options, _, xhr) {
    if (!xhr.crossDomain) {
      xhr.setRequestHeader(CSRF_HEADER, securityToken);
    }
  });
};

setCSRFToken($('meta[name="csrf-token"]').attr('content'));
于 2013-08-04T10:14:26.983 に答える
6

サーバー.js

...
// All Cookies/Sessions/BodyParser go first
app.use(express.csrf());
...
// Get the request
app.post('/ajax', function(req, res){
    res.render('somelayout', {csrf_token: req.session._csrf});
});

somelayout.jade で

input(type='hidden', name='_csrf', value=csrf_token)

CSRF ミドルウェアは、セッションごとに 1 回だけ csrf トークンを生成するため、ユーザーがアクセスしている間はおそらく変更されません。

また、GET および HEAD リクエストでトークンをチェックしません。トークンが要求 (ヘッダー、本文、またはクエリ) にある限り、問題ありません。それだけです。

于 2012-06-26T03:03:21.040 に答える
1

サーバー内:

app.use(function (req, res) {
  res.locals._csrf = req.csrfToken();
  res.locals.csrf_form_html = '<input type="hidden" name="_csrf" value="' + req.csrfToken() + '" >';
  req.next();
});

クライアント内: (swig テンプレート)

var csrf = {{ _csrf|json|safe }};

$.ajaxSetup({
  headers: {
    'X-CSRF-Token': csrf
  }
});

$.post("/create", data, function(result) {
  console.log(result);
}).fail(function(){
  console.log(arguments);
});
于 2014-03-23T16:00:47.287 に答える
0

1. csrf 保護ミドルウェアを追加します。

app.use(csrf({cookie: true}));

// csrf middleware
app.use(function (req, res, next) {
   res.cookie('X-CSRF-Token', req.csrfToken());
   // this line below is for using csrfToken value in normal forms (as a hidden input)
   res.locals.csrfToken = req.csrfToken(); 
   next();
});

// routing setup goes here

2.beforeSend :を使用してコールバックを追加します$.ajaxSetup(すべての ajax 呼び出しの前にこれを追加します)。

$.ajaxSetup({
beforeSend: function (xhr, settings) {
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }

    if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
        // Only send the token to relative URLs i.e. locally.
        xhr.setRequestHeader("X-CSRF-Token", getCookie('X-CSRF-Token'));
    }
}
});

3.それだけです!ajax リクエストを送信できるようになりました。ヘッダーに何も追加したり、csrf を通過するリクエスト パラメータとして追加したりする必要はありません。

于 2017-07-06T09:37:12.743 に答える