在ASP.NET MVC应用程序中使用AngularJS $ http服务时,我遇到了一些传递正确AntiForgertyToken的问题。
我尝试了以下内容:
使用httpInterceptor
设置HTTP请求标头app.factory('httpInterceptorService', function ($q) {
return {
'request': function (config) {
blockUI();
config.headers['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT'; // Disables IE AJAX request caching
config.headers['Cache-Control'] = 'no-cache';
config.headers['Pragma'] = 'no-cache';
config.headers['X-Requested-With'] = 'XMLHttpRequest';
config.headers['__RequestVerificationToken'] = $('[name=__RequestVerificationToken]').val();
return config;
},
通过工厂服务设置HTTP请求标头
app.factory('networkService', function ($http) {
return {
postDataAsAjax: function (url, params) {
debugger;
return $http({
method: 'POST',
url: url,
data: params,
headers: {
'__RequestVerificationToken': $('[name=__RequestVerificationToken]').val(),
'X-Requested-With': 'XMLHttpRequest'
}
}).then(function (result) {
这两种方法都抛出AntiForgeryTokenException。
有没有其他方法可以实现这个目标?
编辑(添加HTTP请求信息)
POST /WebApplication1/Home/Index HTTP/1.1
Host: localhost
Connection: keep-alive
Content-Length: 799
Cache-Control: no-cache
Pragma: no-cache
Origin: http://localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36
Content-Type: application/json;charset=UTF-8
Accept: application/json, text/plain, */*
X-Requested-With: XMLHttpRequest
If-Modified-Since: Mon, 26 Jul 1997 05:00:00 GMT
__RequestVerificationToken: CKCARSoIug5mHnHmUT4ciSmf3pCk1YJkcwq3czo5snfEwTVPBUYLQj7z7w3KKDu001RYk7zuMZ1LEwwWB1tNpZR0agxJK1DjqjMDnQNewLKGCmExANXIJ-Du7lc0LEFw0
Referer: http://localhost/SSP-Working_SourceCode/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: __ngDebug=true; ASP.NET_SessionId=4kcpxz1oj0042ndw4aotx0jl; __RequestVerificationToken_L1NTUC1Xb3JraW5nX1NvdXJjZUNvZGU1=Q8FOz7jJHQHdes02AJvRGglFU_pcz5eqcnZY3QXg37z9k1LMYiPWq-kKbXlYCbAfK0IgLpCtpBax6w-rB1J_NBi7KzGyCuwLCHjKNREjMhQ1; .ASPXFORMSAUTH=CC35114F38FD17866FAF38A1FDC525263A0858EFECFB03AEEED7E9AF7FAA2995262A426D4AA50EB87C47969C3C191BC9B3D31BC67A831C099F286AD3013348B14659632BC54425E3D81C19CB382E175B2DA3755DDFE46D7A79810FB79EBE832D616A299C93CFDA2105576B922C6A1D111A23BB6F9594532C310A15AF2162785A
编辑(添加了自定义防伪标记属性)
public class GlobalAntiForgeryTokenAttribute : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext authorizationContext)
{
var request = authorizationContext.HttpContext.Request;
if (request.HttpMethod.ToUpper() != "POST")
{
return;
}
if (authorizationContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) ||
authorizationContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))
{
return;
}
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = antiForgeryCookie != null ? antiForgeryCookie.Value : null;
AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
}
else
{
new ValidateAntiForgeryTokenAttribute().OnAuthorization(authorizationContext);
}
}
}
编辑(添加HTTP响应)
System.Web.Mvc.HttpAntiForgeryException
:所需的防伪表单字段__RequestVerificationToken
不存在。
答案 0 :(得分:1)
问题在于验证令牌是表单数据的一部分,但您在标题中提供它。
This post告诉您如何构建一个用于验证标头的属性过滤器。
这是我的:
[AttributeUsage(AttributeTargets.Class)]
public class ValidateAntiForgeryTokenOnAjax : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request;
// Only validate POSTs
if (request.HttpMethod == WebRequestMethods.Http.Post)
{
// Ajax POSTs and normal form posts have to be treated differently when it comes
// to validating the AntiForgeryToken
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = antiForgeryCookie != null
? antiForgeryCookie.Value
: null;
AntiForgery.Validate(cookieValue, request.Headers[AntiForgeryConfig.CookieName]);
}
else
{
new ValidateAntiForgeryTokenAttribute()
.OnAuthorization(filterContext);
}
}
}
然后按照以下方式配置角度:
var myApp = angular.module("myApp", ["ngRoute"])
.run(function ($http) {
$http.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
$http.defaults.headers.post["__RequestVerificationToken"] = $("#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]").val();
});
在我的主布局页面上,我声明了这个表单:
<form id="__AjaxAntiForgeryForm" action="#" method="post">@Html.AntiForgeryToken()</form>
答案 1 :(得分:0)
对于那些面临类似问题的人来说,我们的应用程序的问题是前一个开发人员还在requeset POSTing到的MVC控制器操作上定义了默认的“ValidateAntiForgeryToken”属性。
一旦我们从控制器操作中删除了[ValidationAntiForgeryToken],它就开始工作了。
我们有一个自定义防伪标记属性,用于检查标头中的标记,但MVC属性的默认实现仅检查请求主体,这导致此操作失败。