ASP.NET MVCでknockout.js を使った際に ValidateAntiForgeryToken を使用する
http://blogs.yahoo.co.jp/dk521123/35669223.htmlをベースに、セキュリティ強化の一環で、ValidateAntiForgeryToken を使用するサンプルを考える。 ValidateAntiForgeryToken については、以下の関連記事を参照のこと。http://blogs.yahoo.co.jp/dk521123/35641403.html
サンプル
http://stackoverflow.com/questions/2906754/how-can-i-supply-an-antiforgerytoken-when-posting-json-data-using-ajaxhttp://stackoverflow.com/questions/4074199/jquery-ajax-calls-and-the-html-antiforgerytoken
で記載されている方法で、とりあえず実装できた。 ただこれで本当にいいのかって疑問が残るが、ひとまず、記録として残しておく。 # 以下の関連記事に、決定版を記載しておく。http://blogs.yahoo.co.jp/dk521123/35849982.html
モデル
* SampleKnockoutModel.vbNamespace Models Public Class SampleCompanyModel Public Property CountryId As String Public Property CompanyNames As List(Of ListItem) Public Property CompanyIds As List(Of String) End Class End Namespace
ビュー
* Index.vbhtml@ModelType WebAppli.Models.SampleCompanyModel @Code ViewData("Title") = "Index" End Code <h2>Index</h2><br /> @Using (Html.BeginForm( "SendResult", "SampleKnockout", FormMethod.Post, New With {.id = "comForm"})) @Html.AntiForgeryToken() @Html.RadioButtonFor(Function(model) model.CountryId, "JP") @Html.Label("Japan")@<br /> @Html.RadioButtonFor(Function(model) model.CountryId, "US") @Html.Label("USA")@<br /> @<select multiple="multiple" name="@Html.NameFor(Function(model) model.CompanyIds)" data-bind="options: items, optionsText: 'Text', optionsValue: 'Value'" size="7" width="200"></select> @<input type="submit" value="Send" /> End Using <script src="@Url.Content("~/Scripts/jquery-1.10.2.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/knockout-3.4.0.debug.js")" type="text/javascript"></script> <script type="text/javascript"> function ViewModel() { var self = this; self.items = ko.observableArray(); } var viewModel = new ViewModel(); ko.applyBindings(viewModel); var token = $('input[name="__RequestVerificationToken"]').val(); $('input[name="CountryId"]:radio').change(function () { $.ajax({ type: 'POST', url: '@Url.Action("GetList")', // アクセス先のURL data: { __RequestVerificationToken: token, id: $(this).val(), }, }) .done(function (returnData) { viewModel.items(returnData.results); }); }); </script>* SendResult.vbhtml
@ModelType WebAppli.Models.SampleCompanyModel @Code ViewData("Title") = "SendResult" End Code <h2>SendResult</h2> <p>ID : @Model.CountryId </p> @For Each companyId In Model.CompanyIds @<p>Company ID : @companyId</p>@<br /> Next
コントローラ
* CompanyController.vbImports System.Web.Mvc Imports WebAppli.Models Namespace Controllers Public Class CompanyController Inherits Controller Private CompanyInfoDictinary As Dictionary(Of String, List(Of ListItem)) Public Sub New() CompanyInfoDictinary = New Dictionary(Of String, List(Of ListItem)) From { {"JP", New List(Of ListItem) From { New ListItem() With {.Value = "J01", .Text = "Sony"}, New ListItem() With {.Value = "J02", .Text = "Hitachi"}, New ListItem() With {.Value = "J03", .Text = "Toshiba"}, New ListItem() With {.Value = "J04", .Text = "Fujitsu"} } }, {"US", New List(Of ListItem) From { New ListItem() With {.Value = "U01", .Text = "Google"}, New ListItem() With {.Value = "U02", .Text = "Yahoo"}, New ListItem() With {.Value = "U03", .Text = "Microsoft"} } } } End Sub Function Index() As ActionResult Dim model = New SampleCompanyModel() model.CountryId = "JP" Return View(model) End Function <ValidateAntiForgeryToken()> <HttpPost> Function GetList(ByVal id As String) As ActionResult Dim sendingValues = CompanyInfoDictinary(id) Return Json(New With { .results = sendingValues}, JsonRequestBehavior.AllowGet) End Function Function SendResult(ByVal model As SampleCompanyModel) As ActionResult Return View(model) End Function End Class End Namespace