Asp.net-Mvc-4
帶有 SPA 架構的 ValidateAntiForgeryToken
我正在嘗試為 Hot Towel SPA 申請設置註冊和登錄。我基於asp.net 單頁應用程序模板創建了 SimpleMembershipFilters 和 ValidateHttpAntiForgeryTokenAttribute 。
你如何得到
@Html.AntiForgeryToken()在 Durandal SPA 模式下工作的程式碼。
目前我有一個register.html
<section> <h2 data-bind="text: title"></h2> <label>Firstname:</label><input data-bind="value: firstName" type="text" /> <label>Lastname:</label><input data-bind="value: lastName" type="text" /> <label>Email:</label><input data-bind="value: emailAddress" type="text" /> <label>Company:</label><input data-bind="value: company" type="text" /> <br /> <label>Password:</label><input data-bind="value: password1" type="password" /> <label>Re-Enter Password:</label><input data-bind="value: password2" type="password" /> <input type="button" value="Register" data-bind="click: registerUser" class="btn" /> </section>註冊.js:
define(['services/logger'], function (logger) { var vm = { activate: activate, title: 'Register', firstName: ko.observable(), lastName: ko.observable(), emailAddress: ko.observable(), company: ko.observable(), password1: ko.observable(), password2: ko.observable(), registerUser: function () { var d = { 'FirstName': vm.firstName, 'LastName': vm.lastName, 'EmailAddress': vm.emailAddress, 'Company': vm.company, 'Password': vm.password1, 'ConfirmPassword': vm.password2 }; $.ajax({ url: 'Account/JsonRegister', type: "POST", data: d , success: function (result) { }, error: function (result) { } }); }, }; return vm; //#region Internal Methods function activate() { logger.log('Login Screen Activated', null, 'login', true); return true; } //#endregion });在 $ajax 呼叫中如何傳遞 AntiForgeryToken?另外我如何創建令牌?
我會閱讀這篇關於如何使用 javascript 使用防偽令牌的文章。這篇文章是為 WebApi 編寫的,但如果你願意,它可以很容易地應用於 MVC 控制器。
簡短的回答是這樣的:在您的 cshtml 視圖中:
<script> @functions{ public string TokenHeaderValue() { string cookieToken, formToken; AntiForgery.GetTokens(null, out cookieToken, out formToken); return cookieToken + ":" + formToken; } } $.ajax("api/values", { type: "post", contentType: "application/json", data: { }, // JSON data goes here dataType: "json", headers: { 'RequestVerificationToken': '@TokenHeaderValue()' } }); </script>然後在您的 asp.net 控制器中,您需要像這樣驗證令牌:
void ValidateRequestHeader(HttpRequestMessage request) { string cookieToken = ""; string formToken = ""; IEnumerable<string> tokenHeaders; if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders)) { string[] tokens = tokenHeaders.First().Split(':'); if (tokens.Length == 2) { cookieToken = tokens[0].Trim(); formToken = tokens[1].Trim(); } } AntiForgery.Validate(cookieToken, formToken); }您想在標頭中傳遞它的原因是,如果您在請求的查詢字元串或正文內的 ajax 呼叫中將其作為參數數據參數傳遞。然後,您將更難獲得適用於所有不同場景的防偽令牌。因為您必須反序列化正文然後找到令牌。在標題中,它非常一致且易於檢索。
**為光線編輯
這是一個動作過濾器範例,您可以使用它來為 Web api 方法賦予屬性,以驗證是否提供了防偽令牌。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Helpers; using System.Web.Http.Filters; using System.Net.Http; using System.Net; using System.Threading.Tasks; using System.Web.Http.Controllers; using System.Threading; namespace PAWS.Web.Classes.Filters { public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter { public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) { if (actionContext == null) { throw new ArgumentNullException("HttpActionContext"); } if (actionContext.Request.Method != HttpMethod.Get) { return ValidateAntiForgeryToken(actionContext, cancellationToken, continuation); } return continuation(); } private Task<HttpResponseMessage> FromResult(HttpResponseMessage result) { var source = new TaskCompletionSource<HttpResponseMessage>(); source.SetResult(result); return source.Task; } private Task<HttpResponseMessage> ValidateAntiForgeryToken(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) { try { string cookieToken = ""; string formToken = ""; IEnumerable<string> tokenHeaders; if (actionContext.Request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders)) { string[] tokens = tokenHeaders.First().Split(':'); if (tokens.Length == 2) { cookieToken = tokens[0].Trim(); formToken = tokens[1].Trim(); } } AntiForgery.Validate(cookieToken, formToken); } catch (System.Web.Mvc.HttpAntiForgeryException ex) { actionContext.Response = new HttpResponseMessage { StatusCode = HttpStatusCode.Forbidden, RequestMessage = actionContext.ControllerContext.Request }; return FromResult(actionContext.Response); } return continuation(); } } }