如何通过控制器动作和Ajax保护文件下载?

时间:2019-02-03 09:05:55

标签: c# asp.net-mvc security

我有一个应用程序,希望用户能够上传和下载自己的文件。我实现了上传和下载,但是我担心下载操作的XSS漏洞。我只能使用GET方法实现实际下载的文件,但是我想保护它(通常使用POST +防伪令牌)。我该怎么办?

这是我的控制器操作:

// server side
boost::asio::async_read_until(con_handle->socket, con_handle->read_buffer, "\n", handler);
                                                                           ^^^^ delimiter
// client side
boost::asio::write(socket, boost::asio::buffer("test message\n"), error);
                                                         ^^^^ added delimiter

还有我的ajax电话

        public ActionResult DownloadFile(int clientFileId)
        {
            var clientId = GetClientId(clientFileId);
            var client = _unitOfWork.Clients.GetById(clientId);

            if (client == null)
                return HttpNotFound();

            var file = _unitOfWork.ClientFiles.GetById(clientFileId);

            if (file == null)
                return HttpNotFound();

            var practiceId = _unitOfWork.Users.GetPracticeIdForUser(User.Identity.GetUserId());
            if (!AuthorizationHelper.CheckBelongsToPractice(_unitOfWork.Clients, typeof(Client),
                practiceId, client.Id, nameof(Client.Id), nameof(Client.PracticeId)))            
            {
                return new HttpUnauthorizedResult();
            }

            var fileInfo = new FileInfo(file.FilePath);
            var fileName = fileInfo.Name;

            if (!fileInfo.Exists)
                return HttpNotFound();

            var path = Path.Combine(Server.MapPath("~/ClientFiles/" + clientId + "/"), fileName);
            var contentType = MimeMapping.GetMimeMapping(path);
            try
            {
                var contentDisposition = new System.Net.Mime.ContentDisposition
                {
                    FileName = fileName,
                    Inline = false,                    
                };
                Response.AppendHeader("Content-Disposition", contentDisposition.ToString());
                return File(path, contentType, fileName);
            }
            catch (Exception ex)
            {
                new ExceptionlessLogger(ex).Log();
                return new HttpStatusCodeResult(500);
            }
        }

1 个答案:

答案 0 :(得分:2)

我在这里找到了答案:https://codepen.io/chrisdpratt/pen/RKxJNo

$('#client-files-table').on('click', '.js-download', function () {
        var link = $(this);        
        $.ajax({
            url: '/clients/clientfiles/downloadfile?clientFileId=' + link.attr('data-clientfile-id'),
            method: 'POST',
            data: {
                __RequestVerificationToken: getToken()                
            },            
            xhrFields: {
                responseType: 'blob'
            },
            success: function (data, status, xhr) {
                var a = document.createElement('a');
                var url = window.URL.createObjectURL(data);
                a.href = url;
                var header = xhr.getResponseHeader('Content-Disposition');
                var filename = getFileNameByContentDisposition(header);
                a.download = filename;
                a.click();
                window.URL.revokeObjectURL(url);
                loadPartials();
            },
            error: function () {
                toastr.error('Unable to download.');
            }
        });            
    });