将防伪令牌附加到XMLHttpRequest

时间:2019-01-31 14:25:35

标签: javascript ajax asp.net-mvc xmlhttprequest antiforgerytoken

标题说的差不多。这是javascript ...在不验证令牌的情况下工作正常。收到The required anti-forgery form field "__RequestVerificationToken" is not present.错误时,似乎没有看到它。

var downloadEmailSignature = function (control) {
    if (control) {
        let form = $(control).closest('form');
        let token = $(form).find('input[name="__RequestVerificationToken"]').val();

        if (form) {
            let request = new XMLHttpRequest();
            request.open("POST", "Forms/DownloadEmailSignature");
            request.responseType = "blob";
            request.setRequestHeader('RequestVerificationToken', token);
            request.data = form.serialize();
            request.onload = function () {
                if (window.clientData.browser.name === "Internet Explorer") {
                    window.navigator.msSaveBlob(this.response, "EmailSignature.hta");
                }
                else{
                    let url = window.URL.createObjectURL(this.response);
                    let a = document.createElement("a");
                    document.body.appendChild(a);
                    a.href = url;
                    a.download = this.response.name || "download-" + $.now();
                    a.click();
                }
            };
            console.dir(request);
            request.send();
        }
    }
};

以及背后的代码...

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult DownloadEmailSignature(string emailSignature)
    {
        var hta = (MediaItem)SitecoreContext.GetItem<Item>(new Guid("{EE806F14-5BD3-491C-9169-DA701357FB45}"));

        using (var reader = new StreamReader(MediaManager.GetMedia(hta).GetStream().Stream))
        {
            var htaText = reader.ReadToEnd();

            htaText = htaText.Replace("*CARDSTRING*", emailSignature);

            var stream = new MemoryStream(htaText.ToASCIIByteArray());

            return new FileStreamResult(stream, "application/hta");
        }
    }

最后是视图...

<form id="download-email-signature" method="POST" enctype="multipart/form-data">
    @Html.HiddenFor(m => m.EmailSignatureMarkup)
    @Html.AntiForgeryToken()                                          
    @Html.FormIdentifier("FormsController", "DownloadEmailSignature")
    <a href="#" id="download-installer" onclick="downloadEmailSignature(this); return false;" class="btn-primary" style="margin-bottom:10px;margin-top:-10px;text-align:center;">Download installer</a>
</form>

2 个答案:

答案 0 :(得分:0)

如果您可以将XMLHttpRequest替换为$.ajax(因为您已经加载了JQuery),则下面的段应该可以工作。

let form = $(control).closest('form');
let token = $(form).find('input[name="__RequestVerificationToken"]').val();

$.ajax({
    url: '/Home/DownloadEmailSignature',
    type: 'POST',
    data: {
        __RequestVerificationToken: token,
        emailSignature: 'emailSignature value'
    },
    success: function (result) {
        alert(result);
        //your code ....
    }
});

答案 1 :(得分:0)

根据这里的答案:

ValidateAntiForgeryToken purpose, explanation and example

  

MVC的防伪支持将唯一值写入仅HTTP   Cookie,然后将相同的值写入表单。当页面   提交后,如果Cookie值与   表单值。

暗示Cookie必须返回服务器。除非您使用的是IE9(这在此问题上是有问题的),否则它应该可以正常工作。

我建议您使用request.withCredentials = true;来消除任何与CORs相关的奇怪问题。

如果涉及代理,则在返回服务器的途中cookie也可能被剥夺。