从客户端(&)检测到潜在危险的Request.Path值

Kas*_*sem 8 security validation razor asp.net-mvc-3

我理解为什么会这样,但我需要一个解决方法.我在StackOverflow上查看了一些其他问题,但没有一个是有用的.我不想在整个网站上禁用输入验证,因为这绝对是危险的.我只有一个(至少现在)我需要禁用输入验证的地方.

我用[ValidateInput(false)]属性修饰了Action方法,我用Html.Encode对字符串进行编码.但是,我仍然得到同样的错误.这是我的观点:

<div id="sharwe-categories">
    <ul class="menu menu-vertical menu-accordion">
        @foreach(var topLevel in Model)
        {
            var topLevelName = Html.Encode(topLevel.Name);
             <li class="topLevel">
                <h3>  
                    @Html.ActionLink(topLevel.Name, "Index", "Item", new { category = topLevelName }, new {@class = "main"} )
                    <a href="#" class="drop-down"></a>
                </h3>
                <ul>
                    @foreach (var childCategory in topLevel.Children)
                    {
                        var childcategoryName = Html.Encode(childCategory.Name);
                        <li>@Html.ActionLink(childCategory.Name, "Index", "Item", new RouteValueDictionary { { "category", topLevelName }, { "subcategory", childcategoryName } }, null)</li>
                    }
                </ul>
            </li>
        }

    </ul>

</div>
Run Code Online (Sandbox Code Playgroud)

如您所见,没有用户输入.但是一些类别名称中有一些"危险"字符......任何解决方案?

Rob*_*nik 11

尽管Darin的答案是完全可行的,但我不建议使用Scott Hanselman的技术逐步完成所有这些验证.你迟早会陷入深深的......

第二个建议使用ID和虚拟字符串(这对于搜索引擎优化和人们很有用)是一种方法,但有时它们也不可行.想象一下这个请求URL:

/111/Electronics/222/Computers/333/Apple
Run Code Online (Sandbox Code Playgroud)

虽然我们有这些ID,我们可以依赖和人类/ SEO友好的类别名称,这绝对不是所希望的.当我们需要代表一个单独的项目时,ID + Dummy字符串是可行的.在其他情况下,它不是.因为你必须显示类别和子类别,这是一个问题.

所以,你可以做什么?

两种可能的解决方

  1. 清理类别名称只能包含有效字符 - 这可以完成,但如果特权用户不是静态和可编辑的,那么你在这里运气不好,因为即使你现在已经清理它们,有人会在以后输入一些无效的东西

  2. 随时清理您的字符串 - 当您使用类别名称时,清理它并在阅读和使用它时(为了获得实际的类别ID)您可以将提供的(先前已清理的)类别名称与您清理的DB中的值进行比较苍蝇:

    1. 现在在过滤类别时
    2. 在生成类别名称之前

我建议你采取2.2方法.将数据库表扩展为两列:

  • 类别显示名称
  • 类别URL友好名称

您还可以在第二列上设置唯一约束,因此不会发生两个类别(即使它们具有不同的显示名称)将具有相同的URL友好名称.

如何清洁

想到的第一件事就是去除无效字符,但这非常乏味,你很可能会遗漏一些东西.从类别显示名称中获取有效字符会更容易,更明智.我在生成虚拟 URL类别名称时也做了同样的事情.只需取出有效的东西,然后将其余部分分开.它通常工作得很好.这种正则表达式的两个例子:

  1. (\w{2,})- 仅使用字母,数字和下划线以及至少两个(因此我们省略了一个或单个数字和类似的,不会增加任何含义,并且不必要地延长我们的URL
  2. ([a-zA-Z0-9]{2,}) - 只有字母和数字(也是2+)

获取类别显示名称中的所有匹配项,并使用空格/破折号连接它们,并与原始显示名称一起保存.我的另一个问题正是这个问题.

为什么要增加一列?因为您无法在SQL Server中运行正则表达式.如果您正在使用MySql,则可以使用一列并在DB上使用正则表达式.