質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CodeIgniter

CodeIgniterは、PHP向けオープンソースのWebアプリケーションフレームワークです。CodeIgniterは覚える構文が少なく、自由度も高いため、PHPを理解していれば構築が簡単です。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

2回答

1657閲覧

CodeIgniterのCSRFプロテクションを有効化した状態でajaxを使用する

ValveHead

総合スコア6

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CodeIgniter

CodeIgniterは、PHP向けオープンソースのWebアプリケーションフレームワークです。CodeIgniterは覚える構文が少なく、自由度も高いため、PHPを理解していれば構築が簡単です。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

1クリップ

投稿2018/09/01 19:15

編集2018/09/04 20:38

現在、ドットインストールの『PHPでTodo管理アプリを作ろう』を参考に、CodeIgniter3で簡単なTodoアプリを作成中です。
config.phpで$config['csrf_protectin] = TRUEおよび$config['csrf_regenerate'] = TRUEとしたうえで、以下のようなコードをviewに書きました(一部抜粋)。

lang

1<scritp> 2 $(function() { 3 // チェックボックスをクリックして、Todoの完了/未完了を切り替える(取り消し線の表示/非表示を切り替える) 4 $('#todos').on('click', '.update_todo', function() { 5 var id = $(this).parents('li').data('id'); 6 $.ajax({ 7 type: 'POST', 8 url: '<?php echo site_url('todos/update'); ?>', 9 data: { 10 '<?php $this->security->get_csrf_token_name(); ?>': '<?php $this->security->get_csrf_hash(); ?>', 11 id: id 12 }, 13 dataType: 'json' 14 }) 15 .done(function(result) { 16 if (result === '1') { 17 $('#todo_' + id).find('.todo_title').addClass('done'); 18 } else { 19 $('#todo_' + id).find().removeClass('done'); 20 } 21 }); 22 });

上記に加えて、追加および削除の機能も実装済みです。
なお、Todoを追加するための入力フォームにはform_open()を使用しています。

CSRFプロテクションが無効であれば、すべての機能が正常に動作します。
しかし、CSRFプロテクションを有効化すると、ページ読み込み後の最初の1回しかajaxが動いてくれません。

ちなみに$config['csrf_regenerate']をFALSEに設定してみたところ、CSRFプロテクションが無効であるときと同様に、そのような問題は発生しませんでした。

あくまで$config['csrf_protectin] = TRUEおよび$config['csrf_regenerate'] = TRUEとしたうえで、ajaxを利用したいのですが、どなたか解決策をお教えいただけないでしょうか。

どうぞよろしくお願いいたします。

追記

ここを参考に(というか丸写しして)、次のように書きました。

lang

1<script> 2 csrf_token_name = '<?php echo $this->security->get_csrf_token_name(); ?>'; // 追加 3 csrf_cookie_name = '<?php echo $this->config->item('csrf_cookie_name'); ?>'; // 追加 4 $(function() { 5 'use strict'; 6 7 // 追加 -------------------------------------------------------- 8 var object = {}; 9 object[csrf_token_name] = $.cookie(csrf_cookie_name); 10 $.ajaxSetup({ 11 data: object 12 }); 13 $(document).ajaxComplete(function() { 14 object[csrf_token_name] = $.cookie(csrf_cookie_name); 15 $.ajaxSetup({ 16 data: object 17 }); 18 }); 19 // ------------------------------------------------------------- 20 21 // update 22 $('#todos').on('click', '.update_todo', function() { 23 var id = $(this).parents('li').data('id'); 24 $.ajax({ 25 type: 'POST', 26 url: '<?php echo site_url('todos/update'); ?>', 27 data: { 28 id: id 29 }, 30 dataType: 'json' 31 }) 32 .done(function(result) { 33 if (result === '1') { 34 $('#todo_' + id).find('.todo_title').addClass('done'); 35 } else { 36 $('#todo_' + id).find('.todo_title').removeClass('done'); 37 } 38 }); 39 }); 40 41 // create 42 $('#new_todo_form').on('submit', function() { 43 var title = $('#new_todo').val(); 44 $.ajax({ 45 type: 'POST', 46 url: '<?php echo site_url('todos/create'); ?>', 47 data: { 48 title: title 49 }, 50 dataType: 'json' 51 }) 52 .done(function(result) { 53 var $li = $('#todo_template').clone(); 54 $li 55 .attr('id', 'todo_' + result.id) 56 .data('id', result.id) 57 .find('.todo_title').text(title); 58 $('#todos').prepend($li.fadeIn()); 59 $('#new_todo').val('').focus(); 60 }); 61 }) 62 63 // delete 64 $('#todos').on('click', '.delete_todo', function() { 65 var id = $(this).parents('li').data('id'); 66 if (confirm('are you sure?')) { 67 $.ajax({ 68 type: 'POST', 69 url: '<?php echo site_url('todos/delete'); ?>', 70 data: { 71 id: id 72 } 73 }) 74 .done(function() { 75 $('#todo_' + id).fadeOut(400); 76 }); 77 } 78 }); 79 }); 80</script>

こうすると、$config['csrf_regenerate'] = TRUEの状態でもupdateとdeleteのajaxが正常に動きます。
ただ、createを実行すると、"The action you have requested is not allowed."のエラーページに飛ばされてしまいます(Todoの作成自体はできているようです)。

原因をお教えいただければ幸いです。
どうぞよろしくお願いいたします。

追記

上記のコードは、createのところでfalseを返し忘れています。
試してはいませんが、done()メソッドの後にreturn false;を挿入することで、すべてのajaxが正常に動作するかもしれません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

あくまで$config['csrf_protectin] = TRUEおよび$config['csrf_regenerate'] = TRUEとしたうえで、ajaxを利用したいのですが、どなたか解決策をお教えいただけないでしょうか。

$config['csrf_regenerate'] = TRUE としたい理由は何でしょうか?


追記

今回のようなアプリケーションの場合、regenerateを切っておくのが普通というか、有効にする理由がないのでしょうか。

例えば、以下のドキュメントには次のように書かれています。

https://codeigniter.jp/user_guide/3/libraries/security.html

トークンは、すべてのサブミット時に再生成する(デフォルト)か、 CSRF クッキーの生存期間は同一の値で維持するかのどちらかになります。 デフォルトであるトークン再生成はより厳格なセキュリティを提供しますが、 他のトークンが無効になることでユーザビリティの問題をもたらす可能性があります (戻る/進むナビゲーション、複数のタブ/ウィンドウ、非同期アクションなど)。 次の config パラメータを編集することによって、この動作を変更することができます。

今回のケースは非同期アクションに該当しますね。つまり、元々$config['csrf_regenerate'] = TRUE が使えないシーンであるわけです。
それでは、$config['csrf_regenerate'] = TRUE でないとCSRF攻撃にあう可能性が高まるかというと、そんなことはありません。なので、$config['csrf_regenerate'] = TRUE とするために、トリッキーなことをしてしまうと、かえって、その複雑でトリッキーな処理に脆弱性が入る可能性が高くなります。
アプリケーションは単純に書くほどバグは少なくなるわけで、脆弱性もバグの一種ですから、複雑なことをすると脆弱性も傾向としては増えるのです。

投稿2018/09/02 06:36

編集2018/09/02 09:15
ockeghem

総合スコア11701

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ValveHead

2018/09/02 06:59

ockeghemさん、コメントをありがとうございます。 > $config['csrf_regenerate'] = TRUE としたい理由は何でしょうか? あくまで、練習用に作っているので、「$config['csrf_regenerate'] = TRUE」としなければならない現実的な問題はございません。 ただ、もしできるのであれば、その方法を学んでおきたいと思いました。 今回のようなアプリケーションの場合、regenerateを切っておくのが普通というか、有効にする理由がないのでしょうか。
ValveHead

2018/09/02 16:47

ockeghemさん、詳細なご回答をありがとうございます。 引用元のページは開いたことがあるはずですが、よく読めていなかったようです。 $config['csrf_regenerate'] = TRUE が使えない/使うべきでないパターンであるとのこと、承知いたしました。 > アプリケーションは単純に書くほどバグは少なくなるわけで、脆弱性もバグの一種ですから、複雑なことをすると脆弱性も傾向としては増えるのです。 こちらを肝に銘じておきます。 このたびはありがとうございました。
guest

0

$config['csrf_regenerate'] = TRUEとするのであれば、ajax 通信させるごとに ajax 内の token を更新することが必要かと。
ただ、タイミングとか順番とか考えだすと、現実的な実装ではない気がします。

投稿2018/09/02 05:42

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ValveHead

2018/09/02 06:46

te2jiさん、ご回答をありがとうございます。 質問に追記しましたので、もしよろしければご確認いただけないでしょうか。
退会済みユーザー

退会済みユーザー

2018/09/02 07:07

コードレビューするつもりはないので追記のコードは読んでいませんが、多分回答に書いたことをコードに落としてあるんだと思います。変数の変化を追って見ると良いです。
ValveHead

2018/09/02 07:18

承知いたしました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問