客户端与服务器端的文件名清理

时间:2017-10-24 17:09:43

标签: javascript c# jquery asp.net-mvc

从许多单独的网页和控制器上传文件时,当名称中包含HTML实体的文件上传时,我的C#后端会中断:

An exception of type 'System.Web.HttpRequestValidationException' occurred in System.Web.Mvc.dll but was not handled in user code

Additional information: A potentially dangerous Request.Files value was detected from the client (filename="...for_files_#US2023103...").

请注意名称中的HTML实体#,该实体应该只是#。我可以浏览每个网页的JS并强制JS在客户端更改/解码HTML实体(许多小改动),或者我可以更改服务器端代码来处理这个问题,但是我可以我不确定服务器端方法是否可以在不将服务器暴露给漏洞的情况下完成。

为了防止这是一个自以为是的问题,我明确地问:

有没有办法在服务器端转义/验证文件名,而不会抛出异常,并且不会将服务器暴露给漏洞?

以下是我尝试用来替换文件名的代码:

        if (requestContext.HttpContext.Request.Files.Count > 0)
        {
            foreach (HttpPostedFileBase file in requestContext.HttpContext.Request.Files)
            {
                file.FileName = System.Net.WebUtility.HtmlDecode(file.FileName);
            }
        }

这当然是不允许的,因为FileName是HttpPostedFileBase的只读属性。我认为检查文件名,如果它有HTML实体或分号,然后使用更正的名称实例化一个新的HttpPostedFileBase对象可能是明智的。

1 个答案:

答案 0 :(得分:-1)

我不知道您使用的.net框架,但您可以尝试使用https://technet.microsoft.com/en-us/library/ms189575(v=sql.105).aspx方法。

关于安全性的注意事项:在服务器端进行消毒/验证必须。客户端用户体验。你在客户端做的一切都不是很安全,因为你没有办法确保它没有在服务器上重新执行它(这是我对标题的咆哮)

你可以试试

if (requestContext.HttpContext.Request.Files.Count > 0)
{
    var finalDir = "path/to/dir"
    foreach (HttpPostedFileBase file in requestContext.HttpContext.Request.Files)
    {
        var decodedFileName = System.Net.WebUtility.HtmlDecode(file.FileName);

        try
        {
            // Will not overwrite if the destination file already exists.
            if(filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
                throw new Exception('invalid name');
            else
                File.Copy(decodedFileName , Path.Combine(finalDir, Guid.NewGuid()));
        }

        // Catch exception if the file was already copied.
        catch (IOException copyError)
        {
            Console.WriteLine(copyError.Message);
        }
    }
}
根据{{​​3}}

甚至更容易

if (requestContext.HttpContext.Request.Files.Count > 0)
{
    foreach (HttpPostedFileBase file in requestContext.HttpCont
    {
        file.SaveAs(Path.Combine("destination/path/", Guid.NewGuid());
    }
}