app.factory('LoginProvider', function ($resource) { return $resource('/api/login/:id', { id: '@id' }, { 'save': { method: 'POST', headers: { 'X-XSRF-Token': angular.element('input[name="__RequestVerificationToken"]').attr('value') } } }); }); app.factory('OtherProvider', function ($resource) { return $resource('/api/OtherProvider/:id', { id: '@id' }, {'get': { method: 'GET', headers: { 'X-XSRF-Token': angular.element('input[name="__RequestVerificationToken"]').attr('value') } }}); });
using System; using System.Linq; using System.Net.Http; using System.Web.Helpers; using System.Web.Http.Filters; namespace Web.Common.AntiForgery { public sealed class AntiForgeryTokenAttribute : ActionFilterAttribute { public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) { if (actionContext == null) { throw new ArgumentNullException("actionContext"); } var headers = actionContext.Request.Headers; var cookie = headers .GetCookies() .Select(c => c[AntiForgeryConfig.CookieName]) .FirstOrDefault(); var tokenFromHeader = headers.GetValues("X-XSRF-Token").FirstOrDefault(); System.Web.Helpers.AntiForgery.Validate(cookie != null ? cookie.Value : null, tokenFromHeader); base.OnActionExecuting(actionContext); } } }
<%# AntiForgery.GetHtml() %>
namespace Web.Services { [RoutePrefix("api/login")] [Route("{action=Post}")] public class LoginController : ApiController { [AntiForgeryToken] [ResponseType(typeof(LoginResponseModel))] [Route("")] public IHttpActionResult Post([FromBody]LoginRequestModel request) { var response = new LoginResponseModel(); // Business Logic return Ok(response); } } }The code on the master page (or can be placed on the form) is what puts the hidden field containing the token on the page. The ActionFilterAttribute is defined as "AntiForgeryTokenAttribute", but on the Web API side the Attribute is dropped and it is simply "[AntiForgeryToken]".
On the AngularJS side, the $resource POST request adds in the header "X-XSRF-Token", which connects with the hidden field on the master page (or layout). I place it here instead of in the form in case there are multiple forms on the same page that require anti forgery tokens.
AntiForgery.GetHtml() will require <%@ Import Namespace="System.Web.Helpers" %>
ReplyDelete