代码之家  ›  专栏  ›  技术社区  ›  Lorenzo OnoSendai

身份验证令牌和Html.AntiforgeryToken的上载问题(插件不发送cookies)

  •  3
  • Lorenzo OnoSendai  · 技术社区  · 14 年前

    前一段时间,我遇到了一个上传插件的问题,我在这里找到了一个解决方案 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)
    

    这个异常似乎证实了 [验证组织令牌] 正在调用属性。。。但我不明白我的代码哪里出了问题。

    有什么帮助吗?

    编辑 :

    使用调试器,我检查了 __RequestVerificationToken 表单参数,如您所见,它正确地填充了 <%:Html.AntiForgeryToken()%>

    alt text

    编辑2 :

    我也可以确认如果我评论 [验证组织令牌] 论诉讼后 一切如期而至

    编辑3 :

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

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

    哪里 AddAntiForgeryToken() 是在母版页中定义的一个javascript函数,用于支持所有到服务器的ajax post

    <%-- 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 回复  |  直到 8 年前
        1
  •  1
  •   Darin Dimitrov    14 年前

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

    还有一些事情你应该知道,并会抛出同样的例外,虽然我认为它不适用于你的情况,但值得检查。当你使用 Html.AntiforgeryToken() helper如果有一个登录用户他的用户名是发出的cookie的一部分。如果您随后尝试发布到用 [ValidateAntiForgeryToken] 它将验证当前登录的用户是否与发出cookie时的用户相同,如果不是,它将抛出此异常。所以我所看到的是人们使用 Html.AntiforgeryToken() 要以匿名用户的身份生成一些html表单,然后使用AJAX登录用户,一旦登录用户提交表单,它将失败。