【T3b】POSTを処理する(5/5)
プロジェクトタイプ | ASP.NET Core (空) |
---|---|
プロジェクト名 | T3b |
ソリューション名 | PIT3 |
ターゲットフレームワーク | .NET 8.0(長期的なサポート) |
最上位レベルのステートメントを使用しない | 使用する(チェックオフ) |
注意
- 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
- 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
- プロジェクトの作成作業については準備作業を参照せよ.
3b-5. POSTリクエストとフォームについての注意点
今回のようなPOSTリクエストを受け付けるプログラムでは1つ注意するべきことがある. それはPOSTリクエストが,リスト3b-2-2のような こちらの用意したページのフォームによって作られるとは限らない , ということである.
現に,先ほどの手打ちによってPOSTリクエストは用意したフォームによって作られたものではないし, この方法を応用すると フォームの入力欄にはないデータを入力することすらできてしまう . このことを確かめてみよう.
Tera Term で「編集」→「画面のクリア」と「バッファのクリア」の両方をそれぞれクリックして画面を空にしてから, プロジェクトが実行中であることを確認してから,もう一度「ファイル」→「新しい接続」で表3a-4-1の ように入力して「OK」ボタンをクリックして接続を開始しよう. そして_に示すPOSTリクエストを実行を実行してみよう.緑字の部分は図3b-4-1との差分である.
正しく入力できた場合,_のように表示されるはずである.
先ほどと同じく,HTML部分(_♠)をresponse3.html
という名前でファイルに保存して開いてみよう(_).
前後のヘッダーや余計な文字列は削除すること.
ページ上の「フォームデータ(「キーと値」の組)」の部分を見ると,リスト3b-2-2のinput要素で入力欄を用意していたデータである
foo
とbar
だけでなく,入力欄が存在しないはずのbaz
というデータが認識されていることが分かる.
今回のような入力を受け付けるリソース(今回の場合はHoge
コントローラーのDumpPost
アクション)は,
意図しないデータを入力されることを想定してその対策を行うべきである.
この対策を行わないとウェブアプリに意図しない不正なデータを入力されて任意のコードを実行されてしまったり,
クロスサイトリクエストフォージェリと呼ばれる攻撃に利用されてしまうことがある.
幸い,ASP.NET Core はこの対策のための機能を提供している.
ではその機能を試してみよう.このために 先ほどのような入力を受け付けるアクションメソッドに[ValidateAntiForgeryToken]属性 もしくは[AutoValidateAntiforgeryToken]属性を付加する .この属性を付加されたアクションメソッドは こちらの想定したページからのリクエスト以外は受け付けなくなる.
デバッグ実行を停止してから,Controllers/HogeController.cs のDumpPost()
メソッドに_のように書き換えよう.
|
|
書き換えたら実行してみよう.実行してウェブブラウザが起動したら /Hoge/Index
にアクセスして,
開発ツールのネットワークモニターを表示した状態で入力欄に適当な値を入力して「送信」ボタンを押すと,
_,_のように表示されるはずである.
「ファイル」の列が DumpPost
となっている項目を選択して,表示された画面の「応答ヘッダー」の横の「生ヘッダー」を
オンにするとサーバーから400 Bad Request
が戻ってきていることが分かる(_).
先ほどの対策の効果であるが正規のフォームから発せられたリクエストが拒否されてしまっている.
[ValidateAntiForgeryToken]
属性や[AutoValidateAntiforgeryToken]
属性を
つけたアクションでは,フォームデータにアンチフォージェリトークンという隠しデータが含まれていないと,このように
アクションの受付を400 Bad Request
で拒否するようになる.
この隠しデータを送信データに含めるにはフォームの側にも手を加える必要がある.このためには以下のようにする.
デバッグ実行を停止して,フォームを設置しているビューである Views/Hoge/Index.cshtml を開いて, _のように変更しよう.
|
|
_の1行目はタグヘルパーと呼ばれる ASP.NET Core の機能を利用可能にするためのディレクティブである.これは複雑なHTMLの記述を助けるための機能である.
_の17行目では action 属性の代わりに, asp-controller 属性や asp-action 属性といったHTMLでは見慣れない 属性が表れている.これは前述したタグヘルパーの一種で, form 要素の action 属性の値を生成するためのものである. 当然のことながらこれらはHTMLの標準には含まれない ASP.NET Core の独自の属性であり,前処理で通常のHTMLの属性に置き換えられてからクライアント側に送られるため出力結果のHTMLには表れない.
asp-controller 属性と asp-action 属性は 「どのコントローラーの」「どのアクション」かを指定する ものであり,
これらを使用することで,action 属性に適切な値が設定される.今回のウェブアプリの構成では
というURLでアクセスするように構成しているが,
これらのタグヘルパーを使用することでURIのマッピングの設定に基づいて自動的に指定されたコントローラー&アクションのための
URLを生成してくれる.ちなみにこの場合は asp-controller 属性は省略可能である.コントローラーの指定を
省略した場合は,そのビューが属しているコントローラーそのものが指定されたものとみなされる.コントローラー名
/アクション名
またこれらのタグヘルパーには,そのフォームに前述した アンチフォージェリトークンのための隠しデータを追加する という機能もある.
form 要素の action 属性を手動設定せず,かつフォーム用のタグヘルパーを使用している場合は,
フォーム内に type 属性に"hidden"
を指定した input 要素が自動的に挿入され,それにアンチフォージェリトークンのための
隠しデータが埋め込まれる.
ここまで書けたら実行してみよう.実行してウェブブラウザが起動したら /Hoge/Index
にアクセスしてみよう.
ページを右クリックして「ページのソースを表示」をクリックすると,そのページの元となったHTMLが表示される(_).
_に示す通り, .cshtml ファイル上では form 要素に asp-controller や asp-action といったタグヘルパーを指定していたが,
これらは事前処理されて,代わりに action 属性が設定されており,その値としてこのアプリのURLルーティング定義に基づいた,
コントローラー/アクションを指定するURLが設定されていることが分かるだろう.
また,フォーム内に__RequestVerificationToken
という名前の付いた input 要素が追加されていることが分かるだろう.
これが前述したアンチフォージェリトークンである.この値は固定ではなくアクセスするたびに変化する.
[ValidateAntiForgeryToken]
属性や[AutoValidateAntiforgeryToken]
属性をつけたアクションは,
フォームデータにこのアンチフォージェリトークンが含まれているかどうかを検証するようになり,
それが含まれていない限りフォームの処理を拒否するようになる.
(とは言っても,正規にフォームが置いてあるページを取得してから,アンチフォージェリトークンを含めた
任意データをPOSTすることももちろん可能なのでこの方法は不正なデータ入力に対する絶対の防壁ではない
ということは理解しておこう).
それでは実際に送信がうまくいくことを確認しよう.開発ツールのネットワークモニターを表示した状態で 入力欄に適当な値を入力して「送信」ボタンを押す.すると_,_のように表示されるはずである.
「ファイル」の列が DumpPost
となっている項目を選択して,表示された画面の「応答ヘッダー」の横の「生ヘッダー」を
オンにすると,今度は先ほどと異なりサーバーから200 OK
が戻ってきていることが分かる(_).
ページ上の「フォームデータ(「キーと値」の組)」の部分を見ると,アンチフォージェリトークンのための
__RequestVerificationToken
というデータが含まれていることが分かるだろう.
これでフォームのページを経ない POST リクエストを防ぐことができるようになった.
最後に Tera Term を用いて手打ちで POST リクエストを行ってもサーバー側から拒否されることを確認しておこう.
Tera Term を起動していなければ起動して設定ファイル RAW_HTTP.ini を読み込もう.先ほどから起動させたままで あれば「編集」→「画面バッファのクリア」をクリックして画面を空にしておこう. プロジェクトが実行中であることを確認してから ,「ファイル」→「新しい接続」で表3a-4-1のように入力しよう. ただし「TCPポート#」はプロジェクトごとに異なることに注意しよう. 「ホスト」「サービス」「TCPポート#」の3項目を正しく入力したら「OK」ボタンをクリックして接続を開始して,先ほど実行したのと同じ_のテキストメッセージを打ち込もう. 記号種や大文字小文字,空白や改行の個数なども厳密に同じである必要がある .
正しく入力できた場合,_のように表示されるはずである.
Firefox のネットワークモニターで確認したときと同じく,400 Bad Request
が返されてきていることが分かる.
提出時の注意
今回の演習で作成する三個のHTMLファイル,response1~3.html は 作業成果物の一部として提出する必要がある . 提出時は今回作成したソリューション PIT3 のソリューションフォルダ(PIT3.slnがあるのと同じフォルダ; _ )に これらのファイルを置いてから,提出用のZIPファイルを作成すること.
ここまでを確認できたら今回のチュートリアルは完了である. なお今回は課題が出題されている.忘れずに取り組むこと .