4

前段时间我遇到了 Uploadify 插件的问题,我确实找到了这个答案中描述的解决方案。

该问题中的问题主要是由于 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() %>

替代文字

编辑 2

我还可以确认,如果我[ValidateAntiForgeryToken]对 Post Action 发表评论,一切都会按预期进行

编辑 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

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

4

1 回答 1

2

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

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

于 2010-11-23T20:01:01.757 回答