使用身份验证令牌和Html.AntiforgeryToken上传问题(插件不发送cookie)

时间:2010-11-23 14:40:27

标签: asp.net-mvc asp.net-mvc-2 uploadify antiforgerytoken

前段时间我在使用Uploadify插件时出现问题,我确实找到了此answer中描述的解决方案。

该问题的问题主要是由于Uploadify使用flash插件而flash插件不与服务器端代码共享身份验证cookie。

解决方案是使用Authorize属性的自定义版本(代码在该答案中发布)。

属性[TokenizedAuthorize]被放置在控制器类上,如下所示

[TokenizedAuthorize]
[CheckForActiveService]
public partial class DocumentController : BaseController
{
}

前几天我在表单中添加了<%: Html.AntiForgeryToken() %>[ValidateAntiForgeryToken]操作方法,如下例所示:

[HttpPost]
[ValidateAntiForgeryToken]
public virtual ActionResult Upload( HttpPostedFileBase fileData ) {
}

无论如何,我不再能够将文件上传到服务器了。使用调试器,我可以在TokenizedAuthorize代码

的最后一行之后检查
return base.AuthorizeCore( httpContext );

我得到Elmah处理的异常

System.Web.Mvc.HttpAntiForgeryException: invalid or not specified anti forgery token

in System.Web.Mvc.ValidateAntiForgeryTokenAttribute.OnAuthorization(AuthorizationContext filterContext)
in System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor)
in System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)

此异常似乎确认正在调用[ValidateAntiForgeryToken]属性...但我无法理解代码的问题在哪里。

任何帮助?

修改

使用调试器我已经检查了__RequestVerificationToken表单参数的值,正如您所看到的,它已使用<%: Html.AntiForgeryToken() %>

中的值正确填充

alt text

编辑2

如果我对Post Action上的[ValidateAntiForgeryToken]发表评论,我也可以确认一下 一切都按预期工作

编辑3

由于post函数是由uploadify插件完成的ajax调用,因此使用小js函数将AntiForgeryToken添加到post参数中,如下面的代码所示

$('#fileInput').uploadify({
    //other uploadify parameters removed for brevity
    scriptData: AddAntiForgeryToken({ AuthenticationToken: auth }),
});

其中AddAntiForgeryToken()是我的母版页中定义的javascript函数,用于支持服务器上的所有ajax帖子

<%-- used for ajax in AddAntiForgeryToken() --%>
<form id="__AjaxAntiForgeryForm" action="#" method="post">
    <%: Html.AntiForgeryToken() %>
</form>

// Encapsulate the Anti Forgery Token fetching
AddAntiForgeryToken = function (data) {
    data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
    return data;
};

编辑4

Darin直觉是正确的。 Uploadify脚本不向服务器发送任何cookie,因此服务器无法验证AntiForgeryToken。如何在Uploadify scriptData部分中添加cookie?

1 个答案:

答案 0 :(得分:1)

您必须确保在请求中发送与__RequestVerificationToken字段具有相同值的Cookie。通常,此cookie由Html.AntiforgeryToken()发出,并且必须在服务器上完成,因为其值是使用服务器计算机密钥加密的。如果请求是由Flash客户端执行的,我不知道它是否发送cookie。如果不是这种情况,则需要手动发送。

还有一些你应该知道的东西,虽然我不认为它适用于你的情况但值得检查,但它会抛出相同的异常。当您使用Html.AntiforgeryToken()帮助程序时,如果有登录用户,则他的用户名是发出的cookie的一部分。如果您尝试POST到使用[ValidateAntiForgeryToken]修饰的控制器操作,它将验证当前登录的用户是否与发出cookie时的用户相同,如果不是,则会抛出此异常。所以我看到的是人们使用Html.AntiforgeryToken()生成一些html表单作为匿名用户,然后使用AJAX登录用户,一旦登录用户提交表单 - 它将失败。