从客户端检测到具有潜在危险的 Request.Form 值

A potentially dangerous Request.Form value was detected from the client

提问人:Radu094 提问时间:9/17/2008 最后编辑:Peter MortensenRadu094 更新时间:5/25/2023 访问量:1150638

问:

每当用户在我的 Web 应用程序中的页面中发布包含或包含的内容时,我都会引发此异常。<>

我不想讨论因为有人在文本框中输入字符而引发异常或使整个 Web 应用程序崩溃的智能性,但我正在寻找一种优雅的方法来处理这个问题。

捕获异常并显示

发生错误,请返回并重新输入整个表单,但这次请不要使用<

在我看来不够专业。

禁用后验证 () 肯定会避免此错误,但它会使页面容易受到许多攻击。validateRequest="false"

理想情况下:当发生包含 HTML 限制字符的回发时,Form 集合中的已发布值将自动进行 HTML 编码。 所以我的文本框的属性将是.Textsomething & lt; html & gt;

有没有办法从处理程序中做到这一点?

asp.net asp.net-mvc 验证 html-encode request.form

评论

76赞 Drew Noakes 10/14/2010
请注意,如果输入中也有 HTML 实体名称 (&) 或实体编号 ('),则可能会收到此错误。
32赞 Radu094 9/19/2014
好吧,既然这是我的问题,我觉得我可以定义实际的重点是什么:崩溃整个应用程序进程并返回一个通用错误消息,因为有人输入了“<”是矫枉过正。特别是因为您知道大多数人只会“validateRequest=false”来摆脱它,从而重新打开漏洞
10赞 Gyum Fox 5/6/2015
@DrewNoakes:根据我的测试(在 .Net 4.0 中测试),实体名称 (&) 似乎不是问题,尽管实体编号 (') 确实无法通过验证(正如您所说)。如果使用 .Net Reflector 反汇编 System.Web.CrossSiteScriptingValidation.IsDangerousString 方法,则会看到代码专门查找 html 标记(以 < 开头)和实体编号(以 &# 开头)
9赞 stephenbayer 5/27/2015
使用默认的 MVC 项目在 VS2014 中创建一个新站点并运行它。单击注册链接,添加任何电子邮件,然后使用“<P455-0r[!”作为密码。开箱即用的相同错误,不尝试做任何恶意操作,不会显示密码字段,因此不会是 XSS 攻击,但修复它的唯一方法是使用 ValidateInput(false) 完全删除验证?在这种情况下,AllowHtml 建议不起作用,仍然因相同的错误而爆炸。从客户端检测到具有潜在危险的 Request.Form 值 (Password=“<P455-0r[!”)。
0赞 11/3/2016
TL;DR 放入 web.config<httpRuntime requestValidationMode="2.0" />

答:

51赞 Pavel Chuchuva 9/17/2008 #1

您可以对文本框内容进行 HTML 编码,但不幸的是,这并不能阻止异常的发生。根据我的经验,没有办法,您必须禁用页面验证。通过这样做,你是在说:“我会小心的,我保证。

3赞 bastos.sergio 9/17/2008 #2

应使用 Server.HtmlEncode 方法保护站点免受危险输入的影响。

更多信息在这里

评论

3赞 makerofthings7 10/22/2011
使用反 XSS 库来防止此错误...这是不完整的。
0赞 Joren Vandamme 3/6/2019
对如何执行此操作进行更多解释可能会有所帮助。
1146赞 JacquesB 9/17/2008 #3

我认为您试图通过对所有发布的数据进行编码,从错误的角度攻击它。

请注意,“”也可能来自其他外部来源,如数据库字段、配置、文件、源等。<

此外,“”本身并不危险。它只有在特定上下文中才有危险:当编写尚未编码为 HTML 输出的字符串时(由于 XSS)。<

在其他上下文中,不同的子字符串是危险的,例如,如果将用户提供的 URL 写入链接,则子字符串 “” 可能很危险。另一方面,在 SQL 查询中插值字符串时,单引号字符很危险,但如果它是从表单提交的名称的一部分或从数据库字段读取的名称的一部分,则完全安全。javascript:

底线是:您无法过滤危险字符的随机输入,因为在适当的情况下,任何字符都可能是危险的。您应该在某些特定字符可能变得危险的点进行编码,因为它们会交叉到具有特殊含义的不同子语言中。将字符串写入 HTML 时,应使用 Server.HtmlEncode 对 HTML 中具有特殊含义的字符进行编码。如果将字符串传递给动态 SQL 语句,则应对不同的字符进行编码(或者更好的是,让框架使用预处理语句等为您完成)。

当您确定在将字符串传递给 HTML 的所有位置进行 HTML 编码时,然后在文件中的指令中设置。ValidateRequest="false"<%@ Page ... %>.aspx

在 .NET 4 中,可能需要执行更多操作。有时还需要添加到 web.config(引用)。<httpRuntime requestValidationMode="2.0" />

评论

80赞 MGOwen 10/20/2010
对于那些迟到的人:validateRequest=“false” 进入 Page 指令(.aspx 文件的第一行)
63赞 Brian 5/17/2011
提示:添加位置代码,以避免从网站的其他部分扼杀验证提供的有用保护。<httpRuntime requestValidationMode="2.0" />
319赞 Jeremy Holovacs 9/10/2011
在 MVC3 中,这是在 model 属性上。[AllowHtml]
6赞 Alex 7/18/2012
要在 MVC 3 中全局禁用它,您还需要 .GlobalFilters.Filters.Add(new ValidateInputAttribute(false));Application_Start()
18赞 m-smith 7/31/2012
@MGOwen,您还可以通过 中的 将 page 指令添加到 web.config 中。这样做会将该属性应用于所有页面。<pages validateRequest="false" /><system.web />
15赞 blowdart 9/17/2008 #4

我想你可以在一个模块中完成;但这留下了一些悬而未决的问题;如果要将输入保存到数据库,该怎么办?突然之间,因为你要把编码的数据保存到数据库中,你最终会信任它的输入,这可能是一个坏主意。理想情况下,您将原始的未编码数据存储在数据库中,并且每次都进行编码。

在每页级别禁用保护,然后每次都进行编码是更好的选择。

与其使用 Server.HtmlEncode,不如查看来自 Microsoft ACE 团队的更新、更完整的反 XSS 库

5赞 Paweł Hajdan 9/17/2008 #5

只要这些只是“<”和“>”(而不是双引号本身)字符,并且您在<input value=“this” />之类的上下文中使用它们,您就是安全的(而对于<textarea>this one</textarea>您当然会很脆弱)。这可能会简化您的情况,但对于更多内容,请使用其他发布的解决方案之一。

10赞 woany 9/17/2008 #6

如果您确实需要特殊字符(如 、 、 等),请禁用页面验证。然后,确保在显示用户输入时,数据是 HTML 编码的。><

页面验证存在安全漏洞,因此可以绕过该漏洞。此外,不应仅依赖页面验证。

请参见:http://web.archive.org/web/20080913071637/http://www.procheckup.com:80/PDFs/bypassing-dot-NET-ValidateRequest.pdf

评论

0赞 Peter Mortensen 6/24/2017
链接已断开。
5赞 Captain Toad 9/17/2008 #7

如果你只是想告诉你的用户<和>不能被使用,但是,你不希望整个表单事先被处理/回传(并丢失所有输入),你难道不能简单地在字段周围放置一个验证器来筛选那些(也许还有其他潜在的危险)字符?

评论

0赞 mxmissile 2/6/2018
请发帖说“验证者”
36赞 Dominic Pettifer 9/17/2008 #8

请记住,某些 .NET 控件会自动对输出进行 HTML 编码。例如,将 .TextBox 控件上的 Text 属性将自动对其进行编码。这具体意味着转换为 、 和 into .所以要小心这样做......<&lt;>&gt;&&amp;

myTextBox.Text = Server.HtmlEncode(myStringFromDatabase); // Pseudo code

但是,.HyperLink、Literal 和 Label 的 Text 属性不会对内容进行 HTML 编码,因此包装 Server.HtmlEncode();如果要防止输出到页面中并随后执行,则必须围绕这些属性设置的任何内容。<script> window.location = "http://www.google.com"; </script>

做一些实验,看看哪些被编码,哪些没有被编码。

25赞 YORENGOY 1/13/2009 #9

如果不想禁用 ValidateRequest,则需要实现 JavaScript 函数以避免异常。这不是最好的选择,但它有效。

function AlphanumericValidation(evt)
{
    var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode :
        ((evt.which) ? evt.which : 0));

    // User type Enter key
    if (charCode == 13)
    {
        // Do something, set controls focus or do anything
        return false;
    }

    // User can not type non alphanumeric characters
    if ( (charCode <  48)                     ||
         (charCode > 122)                     ||
         ((charCode > 57) && (charCode < 65)) ||
         ((charCode > 90) && (charCode < 97))
       )
    {
        // Show a message or do something
        return false;
    }
}

然后在代码隐藏中,在 PageLoad 事件上,使用以下代码将该属性添加到控件中:

Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);")

评论

5赞 Radu094 10/27/2009
这仍然会使应用程序容易受到捏造的 POST 请求的影响。普通用户在输入、、或引号等字符时会遇到问题,但普通黑客在将格式错误的数据发布到服务器时不会遇到任何问题。我会把这个 waaay 放下。
15赞 jbehren 8/18/2011
@Radu094:此解决方案允许您保留 ValidateRequest=true,这意味着黑客仍会撞到那堵墙。投票赞成,因为这比关闭 ValidateRequest 更不容易受到攻击。
534赞 Zack Peterson 10/9/2009 #10

如果您使用的是 MVC,则此错误有不同的解决方案 ASP.NET:

C# 示例:

[HttpPost, ValidateInput(false)]
public ActionResult Edit(FormCollection collection)
{
    // ...
}

Visual Basic 示例:

<AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
Function Edit(ByVal collection As FormCollection) As ActionResult
    ...
End Function

评论

0赞 12/18/2010
当需要在整个应用程序的一页上时,问题可能会出现
3赞 Shan Plourde 5/29/2011
还可以在类级别添加 [ValidateInput(false)] 属性。如果将其添加到基控制器类中,它将应用于所有控制器方法操作。
0赞 Jack 7/22/2015
@Zack 感谢您的解决方案。另一方面,我想知道是否比 更好,因为是一次为属性定义的,即编辑器字段,并且每当使用它时,都无需将其用于多个操作。你有什么建议?[AllowHtml]ValidateInput(false)[AllowHtml]
1赞 shrey Pav 10/30/2017
@Zack Peterson:使用安全吗?没有安全问题?
46赞 BenMaddox 10/14/2009 #11

可以在 Global.asax 中捕获该错误。我仍然想验证,但显示适当的消息。在下面列出的博客上,提供了这样的示例。

    void Application_Error(object sender, EventArgs e)
    {
        Exception ex = Server.GetLastError();

        if (ex is HttpRequestValidationException)
        {
            Response.Clear();
            Response.StatusCode = 200;
            Response.Write(@"[html]");
            Response.End();
        }
    }

重定向到另一个页面似乎也是对异常的合理响应。

http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html

评论

0赞 Jun Yu 4/8/2022
此页面似乎移到了 romsteady.blogspot.com/2007/06/...
224赞 JordanC 7/30/2010 #12

如果您使用的是 .NET 4.0,请确保在 web.config 文件中的标记内添加以下内容:<system.web>

<httpRuntime requestValidationMode="2.0" />

在 .NET 2.0 中,请求验证仅适用于请求。在 .NET 4.0 中,这已扩展为包括所有请求。通过指定以下命令,可以在处理时恢复为执行 XSS 验证:aspx.aspx

requestValidationMode="2.0"

您可以通过指定以下内容来完全禁用请求验证:

validateRequest="false"

评论

31赞 Hosam Aly 11/4/2010
在标签内。<system.web>
9赞 Filip 12/12/2010
我已将其放在web.config中,但仍然出现错误“潜在危险的Request.Form值”
21赞 Samuel 7/21/2011
看起来 <httpRuntime requestValidationMode=“2.0” /> 仅在计算机上安装了 2.0 框架时才有效。如果根本没有安装 2.0 框架,但只安装了 4.0 框架怎么办?
1赞 tom redfern 10/2/2012
这完全对我有用。其他答案中记录的步骤都不是必需的(包括 validateRequest=“false”)!
75赞 gligoran 11/6/2010 #13

前面的答案很好,但没有人说如何排除单个字段的 HTML/JavaScript 注入验证。我不知道以前的版本,但在 MVC3 Beta 中您可以这样做:

[HttpPost, ValidateInput(true, Exclude = "YourFieldName")]
public virtual ActionResult Edit(int id, FormCollection collection)
{
    ...
}

这仍会验证除排除的字段之外的所有字段。这样做的好处是,您的验证属性仍会验证该字段,但您只是不会收到“从客户端检测到具有潜在危险的 Request.Form 值”异常。

我用它来验证正则表达式。我创建了自己的 ValidationAttribute 来查看正则表达式是否有效。由于正则表达式可以包含看起来像脚本的内容,因此我应用了上述代码 - 仍在检查正则表达式是否有效,但不会检查它是否包含脚本或 HTML。

评论

11赞 Matt Greer 3/24/2011
可悲的是,看起来排除功能已从 MVC 3 RTW 中删除:(
3赞 wilsjd 6/28/2013
它也没有包含在 MVC 4 中
10赞 Mrchief 3/26/2014
在模型的属性上使用,而不是在操作上使用,以实现相同的最终结果。[AllowHtml][ValidateInput]
2赞 gligoran 7/23/2015
@Christof 请注意,我的答案是 5 岁。我已经很久没有遇到这个问题了,所以可能有更好的方法来处理它。关于这两个选项,我认为这取决于您的情况。也许您在多个操作中公开了该模型,并且在某些地方允许或不允许 HTML。在这种情况下,不是一种选择。我建议看看这篇文章:weblogs.asp.net/imranbaloch/...,但它也有些旧,可能已经过时了。[AllowHtml]
1赞 Alex from Jitbit 11/15/2018
仍然有一种方法可以从验证中排除特定方法参数,请在此处查看我的答案:stackoverflow.com/a/50796666/56621
55赞 ranthonissen 11/30/2010 #14

在 ASP.NET MVC 中,需要在 web.config 中设置 requestValidationMode=“2.0” 和 validateRequest=“false”,并将 ValidateInput 属性应用于控制器操作:

<httpRuntime requestValidationMode="2.0"/>

<configuration>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
</configuration>

[Post, ValidateInput(false)]
public ActionResult Edit(string message) {
    ...
}

评论

3赞 tom redfern 10/2/2012
对我来说,没有必要,只是validateRequest="false"requestValidationMode="2.0"
0赞 MC9000 6/13/2015
requestValidationMode=“2.0” 仍会生成带有 HTML编码数据的错误。除了对所有内容进行 base64 编码,然后发送之外,没有其他解决方案。
441赞 Anthony Johnston 9/5/2011 #15

在 ASP.NET MVC(从版本 3 开始)中,可以将 AllowHtml 特性添加到模型上的属性。

它允许请求通过跳过属性的请求验证,在模型绑定期间包含 HTML 标记。

[AllowHtml]
public string Description { get; set; }

评论

14赞 Andiih 3/9/2012
声明式执行此操作比在控制器中要好得多!
0赞 granadaCoder 7/24/2015
这在 MVC 4 中消失了吗?
1赞 Ian Boyd 7/29/2016
和 和有什么不一样?一个相对于另一个的优势是什么?我什么时候想用代替?我什么时候想用完?我什么时候想同时使用两者?两者都使用有意义吗?ValidateInput(false)AllowHtmlAllowHtmlValidateInput(false)ValidateInput(false)AllowHtml
5赞 Anthony Johnston 8/10/2016
ValidateInput 位于方法上,AllowHtml 位于模型的属性上 - 因此您只允许您期望具有 html 的那个 - 而不是全部
1赞 Paras Parmar 6/5/2020
使用 [AllowHtml]。请添加“using System.Web.Mvc;”这帮助我保持安全,并逃脱了我期望接收危险未编码 html 的唯一字段。专业提示: “using System.Web;” //在保存到数据库之前,请确保运行这样的 html 编码器 “string myEncodedString = HttpUtility.HtmlEncode(myString);” //从数据库中检索时,您可以类似地运行这样的解码器 “StringWriter myWriter = new StringWriter();” // 像这样解码编码的字符串。“HttpUtility.HtmlDecode(myEncodedString, myWriter);”
22赞 Piercy 1/27/2012 #16

似乎还没有人提到以下内容,但它为我解决了这个问题。在有人说“是”之前,它是 Visual Basic......呸。

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Example.aspx.vb" Inherits="Example.Example" **ValidateRequest="false"** %>

我不知道是否有任何缺点,但对我来说,这太棒了。

评论

0赞 TheAlbear 10/22/2014
适用于 Web 窗体 c# 或 VB
9赞 Trisped 2/11/2012 #17

您还可以使用 JavaScript 的 escape(string) 函数来替换特殊字符。然后服务器端使用 Server。URLDecode(string) 将其切换回来。

这样,您就不必关闭输入验证,其他程序员会更清楚地知道字符串可能包含 HTML 内容。

30赞 Mahdi jokar 3/15/2012 #18

在 web.config 文件的标记中,插入具有属性 requestValidationMode=“2.0” 的 httpRuntime 元素。此外,在 pages 元素中添加 validateRequest=“false” 属性。

例:

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>

评论

1赞 tom redfern 10/2/2012
对我来说,validateRequest=“false”不是必需的,只有requestValidationMode=“2.0”
3赞 Carter Medlin 11/28/2012
“pages”部分必须位于“system.web”部分内。
0赞 MC9000 6/13/2015
危险的答案,再一次。
0赞 Jack 2/23/2016
我两者都需要。谢谢
10赞 magritte 3/16/2012 #19

这里的其他解决方案很好,但是必须将 [AllowHtml] 应用于每个 Model 属性有点令人痛苦,尤其是当您在一个大小合适的网站上有超过 100 个模型时。

如果像我一样,你想把这个(恕我直言毫无意义)功能转移到全场,你可以覆盖你的基本控制器中的 Execute() 方法(如果你还没有基本控制器,我建议你做一个,它们对于应用通用功能非常有用)。

    protected override void Execute(RequestContext requestContext)
    {
        // Disable requestion validation (security) across the whole site
        ValidateRequest = false;
        base.Execute(requestContext);
    }

只需确保你对来自用户输入的视图的所有内容进行 HTML 编码(无论如何,这是 ASP.NET MVC 3 和 Razor 中的默认行为,因此除非出于某种奇怪的原因,否则您正在使用 Html.Raw(),否则您不需要此功能。

14赞 Jaider 7/18/2012 #20

在 ASP.NET 中,您可以捕获异常并对其执行一些操作,例如显示友好消息或重定向到另一个页面......此外,您还可以自己处理验证...

显示友情提示:

protected override void OnError(EventArgs e)
{
    base.OnError(e);
    var ex = Server.GetLastError().GetBaseException();
    if (ex is System.Web.HttpRequestValidationException)
    {
        Response.Clear();
        Response.Write("Invalid characters."); //  Response.Write(HttpUtility.HtmlEncode(ex.Message));
        Response.StatusCode = 200;
        Response.End();
    }
}
7赞 Ryan 8/3/2012 #21

我最终在每次回发之前使用 JavaScript 来检查您不想要的字符,例如:

<asp:Button runat="server" ID="saveButton" Text="Save" CssClass="saveButton" OnClientClick="return checkFields()" />

function checkFields() {
    var tbs = new Array();
    tbs = document.getElementsByTagName("input");
    var isValid = true;
    for (i=0; i<tbs.length; i++) {
        if (tbs(i).type == 'text') {
            if (tbs(i).value.indexOf('<') != -1 || tbs(i).value.indexOf('>') != -1) {
                alert('<> symbols not allowed.');
                isValid = false;
            }
        }
    }
    return isValid;
}

当然,我的页面主要是数据输入,很少有元素进行回发,但至少它们的数据被保留了下来。

评论

0赞 Shilpa Soni 9/12/2014
应该有大括号而不是小括号。比如 ' if (tbs[i].type == 'text') {' 代替 ' if (tbs(i).type == 'text') {'
9赞 Leniel Maccaferri 8/14/2012 #22

我也收到这个错误。

在我的例子中,用户在角色名称中输入了一个重音字符(关于 ASP.NET 成员资格提供程序)。á

我将角色名称传递给向用户授予该角色的方法,但发布请求惨遭失败......$.ajax

我这样做是为了解决问题:

而不是

data: { roleName: '@Model.RoleName', users: users }

执行此操作

data: { roleName: '@Html.Raw(@Model.RoleName)', users: users }

@Html.Raw做到了。

我得到的角色名称是HTML值。带有 HTML 实体的此值被 MVC 阻止 ASP.NET。现在,我以应有的方式获取参数值:并且 MVC 引擎将不再阻止请求 ASP.NET。roleName="Cadastro b&#225;s"&#225;roleNameroleName="Cadastro Básico"

122赞 Carter Medlin 11/28/2012 #23

对于 ASP.NET 4.0,您可以通过将标记全部放在一个元素中来允许标记作为特定页面的输入,而不是整个网站的输入。这将确保您的所有其他页面都是安全的。您不需要放入 .aspx 页面。<location>ValidateRequest="false"

<configuration>
...
  <location path="MyFolder/.aspx">
    <system.web>
      <pages validateRequest="false" />
      <httpRuntime requestValidationMode="2.0" />
    </system.web>
  </location>
...
</configuration>

在 web.config 中控制它更安全,因为您可以在网站级别查看哪些页面允许将标记作为输入。

您仍然需要以编程方式验证禁用请求验证的页面上的输入。

评论

0赞 GlennG 2/13/2015
有关 requestValidationMode=2|4 的更多信息,请访问:msdn.microsoft.com/en-us/library/...
0赞 Fandango68 3/11/2015
可悲的是,这不适用于 ASP.net 2.0。删除 httpRuntime 行,它将起作用。
0赞 Carter Medlin 6/17/2015
我添加了一个警告,提醒人们在禁用验证时手动验证输入。
4赞 Mike S. 2/18/2013 #24

这些建议都不适合我。无论如何,我不想关闭整个网站的此功能,因为 99% 的时间我不希望我的用户将 HTML 放在 Web 表单上。我刚刚创建了自己的解决方法,因为我是唯一一个使用这个特定应用程序的人。我在代码隐藏中将输入转换为 HTML,并将其插入到我的数据库中。

50赞 flakomalo 4/26/2013 #25

这个问题的答案很简单:

var varname = Request.Unvalidated["parameter_name"];

这将禁用对特定请求的验证。

评论

1赞 Beska 11/5/2014
仅适用于 ASP.NET 4.5(以及之后的任何版本)。4.5 之前版本不支持此功能。
3赞 Chris Gillum 11/19/2014
我希望我能以这种方式向上颠簸。我正在使用 .NET 4.5,这正是我所需要的,因为我没有使用 MVC,我无法更改 web.config。
1赞 Fandango68 3/18/2015
是的,但是如果您使用的是 .Net 2 呢?我们中的一些人别无选择
0赞 max4ever 4/15/2015
这得到 POST 或 GET 参数?
0赞 ebyrob 3/8/2017
你是说这可以防止已经抛出的异常吗?或者 .net 4.5 是否会延迟异常和验证,直到实际从 ?Request
6赞 Ady Levy 6/1/2013 #26

您可以使用类似的东西:

var nvc = Request.Unvalidated().Form;

以后,应该可以工作。nvc["yourKey"]

评论

0赞 habib 5/27/2020
谢谢,您的回答节省了我很多时间
22赞 Sel 12/8/2013 #27

另一种解决方案是:

protected void Application_Start()
{
    ...
    RequestValidator.Current = new MyRequestValidator();
}

public class MyRequestValidator: RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        bool result = base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);

        if (!result)
        {
            // Write your validation here
            if (requestValidationSource == RequestValidationSource.Form ||
                requestValidationSource == RequestValidationSource.QueryString)

                return true; // Suppress error message
        }
        return result;
    }
}

评论

0赞 Walden Leverich 5/2/2014
好!不知道替换请求验证器的能力。我没有像你那样说“好的”,而是扩展了这个想法,不验证以“_NoValidation”结尾的字段作为其名称。代码如下。
0赞 Sel 1/28/2015
Walden Leverich,要执行此操作,请参阅 [AllowHtml] attribure
0赞 Walden Leverich 1/30/2015
选择,是的,在 MVC 环境中可以工作。但是在 Web 表单应用程序中,我没有一个模型来做到这一点。:-)
43赞 A.Dara 1/29/2014 #28

对于 MVC,通过添加

[验证输入(false)]

在控制器中的每个操作上方。

评论

0赞 PandaWood 3/24/2016
在它通过配置的路由到达控制器方法的情况下,这似乎不起作用。
0赞 PandaWood 3/24/2016
实际上,技术上的解释是,这仅在有问题的字符位于“查询字符串”中时才有效......如果它位于请求路径中,则 Validation 属性不起作用
4赞 Walden Leverich 5/2/2014 #29

正如我对 Sel 答案的评论中所指出的,这是我们对自定义请求验证器的扩展。

public class SkippableRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        if (collectionKey != null && collectionKey.EndsWith("_NoValidation"))
        {
            validationFailureIndex = 0;
            return true;
        }

        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}
12赞 Jason Shuler 9/16/2014 #30

我找到了一个使用 JavaScript 对数据进行编码的解决方案,该数据在 .NET 中解码(并且不需要 jQuery)。

  • 使文本框成为 HTML 元素(如 textarea)而不是 ASP 元素。
  • 添加隐藏字段。
  • 将以下 JavaScript 函数添加到标头中。

    函数 boo() { targetText = document.getElementById(“隐藏字段1”); sourceText = document.getElementById(“用户框”); targetText.value = 转义(sourceText.innerText); }

在 textarea 中,包含一个调用 boo() 的 onchange:

<textarea id="userbox"  onchange="boo();"></textarea>

最后,在 .NET 中,使用

string val = Server.UrlDecode(HiddenField1.Value);

我知道这是单向的 - 如果你需要双向,你必须发挥创意,但如果你无法编辑 web.config,这提供了一个解决方案

这是我(MC9000)通过jQuery提出并使用的示例:

$(document).ready(function () {

    $("#txtHTML").change(function () {
        var currentText = $("#txtHTML").text();
        currentText = escape(currentText); // Escapes the HTML including quotations, etc
        $("#hidHTML").val(currentText); // Set the hidden field
    });

    // Intercept the postback
    $("#btnMyPostbackButton").click(function () {
        $("#txtHTML").val(""); // Clear the textarea before POSTing
                               // If you don't clear it, it will give you
                               // the error due to the HTML in the textarea.
        return true; // Post back
    });


});

和标记:

<asp:HiddenField ID="hidHTML" runat="server" />
<textarea id="txtHTML"></textarea>
<asp:Button ID="btnMyPostbackButton" runat="server" Text="Post Form" />

这很好用。如果黑客试图通过绕过 JavaScript 来发帖,他们只会看到错误。您也可以将所有这些编码的数据保存在数据库中,然后取消转义(在服务器端),并在其他地方显示之前解析和检查攻击。

评论

0赞 Fandango68 3/18/2015
这是一个很好的解决方案。这是一种适当的手动方法,可以自己控制它,而不会使整个网站或页面失效
0赞 MC9000 6/13/2015
确保对文本区域使用 HTML 标记,而不是 ASP.Net 控件(即 no runat=“server”),然后对隐藏的控件使用 ASP.Net hidden 控件。这是我见过的最好的解决方案,没有妥协任何东西。当然,您希望在服务器端解析 XSS 和 SQL 注入的数据,但至少您可以发布 HTML
0赞 Nate Anderson 9/13/2016
escape(...)可能需要很长时间。就我而言,标记是一个完整的 (2MB) XML 文件。你可能会问,“你为什么不直接使用和......我同意你的看法:)<input type="file"...
-2赞 Devendra Patel 3/31/2015 #31

试用

Server.Encode

Server.HtmlDecode在发送和接收时。

评论

1赞 MC9000 6/13/2015
你甚至不能走那么远(也就是说你不能回发,所以你在代码隐藏上所做的任何事情都不会起作用)进行验证 - 用户问题的重点。
12赞 vakeel 6/15/2015 #32

原因

默认情况下,ASP.NET 会验证所有输入控件是否存在可能导致跨站点脚本 (XSS) 和 SQL 注入的潜在不安全内容。因此,它通过抛出上述异常来禁止此类内容。默认情况下,建议允许在每次回发时进行此检查。

溶液

在许多情况下,您需要通过富文本框或富文本编辑器将 HTML 内容提交到您的页面。在这种情况下,可以通过将指令中的 ValidateRequest 标记设置为 false 来避免此异常。@Page

<%@ Page Language="C#" AutoEventWireup="true" ValidateRequest = "false" %>

这将禁用对已将 ValidateRequest 标志设置为 false 的页面的请求的验证。如果要禁用此功能,请检查整个 Web 应用程序;需要在 web.config <system.web> 部分中将其设置为 false

<pages validateRequest ="false" />

对于 .NET 4.0 或更高版本的框架,还需要在 <system.web> 部分中添加以下行才能使上述工作正常工作。

<httpRuntime requestValidationMode = "2.0" />

就是这样。我希望这能帮助您摆脱上述问题。

引用者: ASP.Net 错误:从客户端检测到具有潜在危险的 Request.Form 值

15赞 Durgesh Pandey 12/10/2015 #33

如果您使用的是框架 4.0,则 web.config 中的条目 (<pages validateRequest=“false” />)

<configuration>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
</configuration>

如果使用的是框架 4.5,则 web.config 中的条目 (requestValidationMode=“2.0”)

<system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" requestValidationMode="2.0"/>
</system.web>

如果你只想要一个页面,那么,在你的aspx文件中,你应该把第一行放在这样:

<%@ Page EnableEventValidation="false" %>

如果您已经有类似 <%@ Page 的东西,那么只需添加其余的 =>EnableEventValidation="false" %>

我建议不要这样做。

6赞 Sel 2/25/2016 #34

您可以在自定义模型活页夹中自动对字段进行 HTML 编码。我的解决方案有些不同,我将错误放在 ModelState 中并在字段附近显示错误消息。修改此代码以自动编码很容易

 public class AppModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            try
            {
                return base.CreateModel(controllerContext, bindingContext, modelType);
            }
            catch (HttpRequestValidationException e)
            {
                HandleHttpRequestValidationException(bindingContext, e);
                return null; // Encode here
            }
        }
        protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext,
            PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
        {
            try
            {
                return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
            }
            catch (HttpRequestValidationException e)
            {
                HandleHttpRequestValidationException(bindingContext, e);
                return null; // Encode here
            }
        }

        protected void HandleHttpRequestValidationException(ModelBindingContext bindingContext, HttpRequestValidationException ex)
        {
            var valueProviderCollection = bindingContext.ValueProvider as ValueProviderCollection;
            if (valueProviderCollection != null)
            {
                ValueProviderResult valueProviderResult = valueProviderCollection.GetValue(bindingContext.ModelName, skipValidation: true);
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            }

            string errorMessage = string.Format(CultureInfo.CurrentCulture, "{0} contains invalid symbols: <, &",
                     bindingContext.ModelMetadata.DisplayName);

            bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorMessage);
        }
    }

在Application_Start:

ModelBinders.Binders.DefaultBinder = new AppModelBinder();

请注意,它仅适用于表单字段。危险值未传递给控制器模型,但存储在 ModelState 中,并且可以在窗体上重新显示,并显示错误消息。

URL 中的危险字符可以这样处理:

private void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    HttpContext httpContext = HttpContext.Current;

    HttpException httpException = exception as HttpException;
    if (httpException != null)
    {
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        var httpCode = httpException.GetHttpCode();
        switch (httpCode)
        {
            case (int)HttpStatusCode.BadRequest /* 400 */:
                if (httpException.Message.Contains("Request.Path"))
                {
                    httpContext.Response.Clear();
                    RequestContext requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
                    requestContext.RouteData.Values["action"] ="InvalidUrl";
                    requestContext.RouteData.Values["controller"] ="Error";
                    IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
                    IController controller = factory.CreateController(requestContext, "Error");
                    controller.Execute(requestContext);
                    httpContext.Server.ClearError();
                    Response.StatusCode = (int)HttpStatusCode.BadRequest /* 400 */;
                }
                break;
        }
    }
}

错误控制器:

public class ErrorController : Controller
 {
   public ActionResult InvalidUrl()
   {
      return View();
   }
}   

评论

0赞 PJ7 5/2/2018
来这里只是为了发布这个。可惜它将永远埋没在第二页上——恕我直言,这是最好的解决方案。
1赞 Voigt 4/19/2016 #35

使用Server.HtmlEncode("yourtext");

1赞 Peter 1/16/2017 #36

对于我们这些仍然停留在网络表单上的人,我找到了以下解决方案,使您能够仅禁用一个字段的验证!(我不想在整个页面上禁用它。

VB.NET:

Public Class UnvalidatedTextBox
    Inherits TextBox
    Protected Overrides Function LoadPostData(postDataKey As String, postCollection As NameValueCollection) As Boolean
        Return MyBase.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form)
    End Function
End Class

C#:

public class UnvalidatedTextBox : TextBox
{
    protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        return base.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form);
    }
}

现在只需使用 而不是 ,它应该允许所有字符(这非常适合密码字段!<prefix:UnvalidatedTextBox id="test" runat="server" /><asp:TextBox

1赞 dpant 1/28/2018 #37

最后但并非最不重要的一点是,请注意 ASP.NET 数据绑定控件在数据绑定期间自动对值进行编码。这将更改 中包含的所有 ASP.NET 控件(TextBox、Label 等)的默认行为。以下示例演示 ( 设置为 false):ItemTemplateValidateRequest

aspx的

<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication17._Default" %> <html> <body>
    <form runat="server">
        <asp:FormView ID="FormView1" runat="server" ItemType="WebApplication17.S" SelectMethod="FormView1_GetItem">
            <ItemTemplate>
                <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
                <asp:Label ID="Label1" runat="server" Text="<%#: Item.Text %>"></asp:Label>
                <asp:TextBox ID="TextBox2" runat="server" Text="<%#: Item.Text %>"></asp:TextBox>
            </ItemTemplate>
        </asp:FormView>
    </form> 

代码隐藏

public partial class _Default : Page
{
    S s = new S();

    protected void Button1_Click(object sender, EventArgs e)
    {
        s.Text = ((TextBox)FormView1.FindControl("TextBox1")).Text;
        FormView1.DataBind();
    }

    public S FormView1_GetItem(int? id)
    {
        return s;
    }
}

public class S
{
    public string Text { get; set; }
}
  1. 案例提交价值:&#39;

Label1.Text价值:&#39;

TextBox2.Text价值:&amp;#39;

  1. 案例提交价值:<script>alert('attack!');</script>

Label1.Text价值:<script>alert('attack!');</script>

TextBox2.Text价值:&lt;script&gt;alert(&#39;attack!&#39;);&lt;/script&gt;

0赞 KiranC 3/16/2018 #38

在 .Net 4.0 及更高版本中(通常情况下),将以下设置放在 system.web 中

<system.web>
     <httpRuntime requestValidationMode="2.0" />
2赞 Chris Catignani 3/30/2018 #39

我看到有很多关于这个的文章......我没有看到提到这一点。 自 .NET Framework 4.5 以来,此功能已可用

控件的 ValidateRequestMode 设置是一个不错的选择。 这样,页面上的其他控件仍受保护。 无需更改 web.config。

 protected void Page_Load(object sender, EventArgs e)
 {
     txtMachKey.ValidateRequestMode = ValidateRequestMode.Disabled;
 }

评论

1赞 Chris Catignani 1/9/2019
@PruTahan....你需要对每个帖子发表评论,因为?OP 错误消息是由多种不同原因中的任何一个引起的。
3赞 Magnus 4/4/2018 #40

解决方案

我不喜欢关闭后验证(validateRequest=“false”)。另一方面,仅仅因为无辜的用户碰巧打字或其他东西而导致应用程序崩溃是不可接受的。<x

因此,我编写了一个客户端 javascript 函数 (xssCheckValidates) 来进行初步检查。当尝试发布表单数据时,将调用此函数,如下所示:

<form id="form1" runat="server" onsubmit="return xssCheckValidates();">

该功能非常简单,可以改进,但它正在发挥作用。

请注意,这样做的目的不是为了保护系统免受黑客攻击,而是为了保护用户免受不良体验的影响。在服务器上完成的请求验证仍处于打开状态,这是系统保护的(部分)(在它能够这样做的范围内)。

我之所以在这里说“部分”,是因为我听说内置的请求验证可能还不够,因此可能需要其他补充手段才能获得全面保护。但是,同样,我在这里介绍的 javascript 函数与保护系统无关。它只是为了确保用户不会有糟糕的体验。

你可以在这里尝试一下:

    function xssCheckValidates() {
      var valid = true;
      var inp = document.querySelectorAll(
          "input:not(:disabled):not([readonly]):not([type=hidden])" +
          ",textarea:not(:disabled):not([readonly])");
      for (var i = 0; i < inp.length; i++) {
        if (!inp[i].readOnly) {
          if (inp[i].value.indexOf('<') > -1) {
            valid = false;
            break;
          }
          if (inp[i].value.indexOf('&#') > -1) {
            valid = false;
            break;
          }
        }
      }
      if (valid) {
        return true;
      } else {
        alert('In one or more of the text fields, you have typed\r\nthe character "<" or the character sequence "&#".\r\n\r\nThis is unfortunately not allowed since\r\nit can be used in hacking attempts.\r\n\r\nPlease edit the field and try again.');
        return false;
      }
    }
<form onsubmit="return xssCheckValidates();" >
  Try to type < or &# <br/>
  <input type="text" /><br/>
  <textarea></textarea>
  <input type="submit" value="Send" />
</form>

评论

0赞 user169771 4/5/2018
您应该假设在客户端上运行的任何代码都将被破坏。
2赞 Magnus 4/5/2018
@user169771,再读一遍我的答案,尤其是以“请注意,这样做的目的不是为了保护系统免受黑客攻击......”开头的部分。
2赞 figolu 5/4/2018 #41

我知道这个问题是关于表单发布,但我想为在其他情况下收到此错误的人添加一些详细信息。它也可能发生在用于实现 Web 服务的处理程序上。

假设您的 Web 客户端使用 ajax 发送 POST 或 PUT 请求,并将 json 或 xml 文本或原始数据(文件内容)发送到您的 Web 服务。由于 Web 服务不需要从 Content-Type 标头获取任何信息,因此 JavaScript 代码未将此标头设置为 ajax 请求。但是,如果您没有在 POST/PUT ajax 请求上设置此标头,Safari 可能会添加此标头:“Content-Type: application/x-www-form-urlencoded”。我在 iPhone 上的 Safari 6 上观察到了这一点,但其他 Safari 版本/操作系统或 Chrome 可能会做同样的事情。因此,当收到此 Content-Type 标头时,.NET Framework 的某些部分假定请求正文数据结构对应于 html 表单发布,而事实并非如此,并引发了 HttpRequestValidationException 异常。首先要做的显然是始终将 Content-Type 标头设置为 POST/PUT ajax 请求上的表单 MIME 类型以外的任何内容,即使它对您的 Web 服务毫无用处。

我还发现了这个细节:
在这些情况下,当您的代码尝试访问 HttpRequest.Params 集合时,将引发 HttpRequestValidationException 异常。但令人惊讶的是,当它访问 HttpRequest.ServerVariables 集合时,此异常不会出现。这表明,虽然这两个集合看起来几乎相同,但一个通过安全检查访问请求数据,而另一个则不然。

6赞 Wahid Masud 7/24/2018 #42

对于那些不使用模型绑定、从 Request.Form 中提取每个参数、确定输入文本不会造成伤害的人,还有另一种方法。这不是一个很好的解决方案,但它可以完成这项工作。

在客户端,将其编码为 uri,然后发送。
例如:

encodeURIComponent($("#MsgBody").val());  

在服务器端,接受它并将其解码为 uri。
例如:

string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Web.HttpUtility.UrlDecode(HttpContext.Current.Request.Form["MsgBody"]) : 
null;  

string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Uri.UnescapeDataString(HttpContext.Current.Request.Form["MsgBody"]) : 
null; 

请寻找 和 之间的区别UrlDecodeUnescapeDataString

5赞 maozx 12/3/2018 #43

就我而言,使用 asp:Textbox 控件(Asp.net 4.5),而不是为我使用的 All Page 设置所有页面validateRequest="false"

<asp:TextBox runat="server" ID="mainTextBox"
            ValidateRequestMode="Disabled"
 ></asp:TextBox>

在导致异常的文本框上。

0赞 Sanjeev Singh 5/7/2020 #44

如何修复 ASP.NET 4.6.2 中 AjaxExtControls 的此问题:

我们在使用 AjaxExtControls 富文本编辑器时遇到了同样的问题。此问题在从 .NET 2.0 升级到 .NET 4.5 后立即开始。我查看了所有 SOF 答案,但找不到不损害 .NET 4.5 提供的安全性的解决方案。

修复 1(不推荐,因为它会降低应用程序安全性):我在更改此属性后进行了测试,它有效,但我担心安全功能。因此,修复就像降低整个应用程序的安全性一样。requestValidationMode = "2.0

修复 2(推荐):由于此问题仅发生在 AjaxExtControl 之一上,因此我最终能够使用以下简单代码解决此问题:

editorID.value = editorID.value.replace(/>/g, "&gt;");
editorID.value = editorID.value.replace(/</g, "&lt;");

此代码在向服务器发送请求之前在客户端 (javascript) 执行。请注意,editorID 不是我们在 html/aspx 页面上拥有的 ID,而是 AjaxExtControl 内部使用的富文本编辑器的 ID。

1赞 syntap 4/9/2021 #45

我有一个 Web 窗体应用程序,它对文本框注释字段有这个问题,用户有时会在其中粘贴电子邮件文本,电子邮件标题信息中的“<”和“>”字符会潜入其中并引发此异常。

我从另一个角度解决了这个问题......我已经在使用 Ajax 控件工具包,因此我能够使用 FilteredTextBoxExtender 来防止这两个字符进入文本框。然后,用户复制粘贴文本将获得他们所期望的内容,减去这些字符。

<asp:TextBox ID="CommentsTextBox" runat="server" TextMode="MultiLine"></asp:TextBox>
<ajaxToolkit:FilteredTextBoxExtender ID="ftbe" runat="server" TargetControlID="CommentsTextBox" filterMode="InvalidChars" InvalidChars="<>" />
0赞 Colin 12/13/2021 #46

没有一个答案对我有用。然后我发现,如果我删除以下代码,我就可以让它工作:

//Register action filter via Autofac rather than GlobalFilters to allow dependency injection
builder.RegisterFilterProvider();
builder.RegisterType<OfflineActionFilter>()
    .AsActionFilterFor<Controller>()
    .InstancePerLifetimeScope();

我只能得出结论,Autofac 的 RegisterFilterProvider 中的某些内容破坏或覆盖了 validateRequest 属性

0赞 jcs 1/27/2022 #47

即使在添加到 web.config 之后,我仍然在使用 WIF 进行身份验证的应用程序中不断收到错误。
对我来说,解决的是在元素内部添加。
<httpRuntime requestValidationMode="2.0"><sessionState mode="InProc" cookieless="UseUri"/><system.web>

0赞 Gauravsa 5/25/2023 #48

不建议接受的答案。在服务器端,我们使用了这个:

在 asp.net 中创建一个隐藏字段并对其进行编码。

hiddenFieldMessage.Value = Uri.EscapeDataString(dangerousString);

然后在 Javascript 中,创建一个文本区域并解码编码值。

<script>
    (function () {
        
        const content = document.getElementById('<%= hiddenFieldMessage.ClientID %>').value;
        // decode the content back to html
        var textArea = document.createElement("textarea");
        textArea.innerHTML = decodeURIComponent(document.getElementById('<%= hiddenFieldMessage.ClientID %>').value);
        const content = textArea.value;  // decoded value
   })

评论

0赞 Radu094 6/23/2023
好吧,问题更多的是关于处理 POST(即客户端到服务器),而不是将转义字符串发送到客户端文本区域。顺便说一句,是什么阻止您将该字符串直接转义到控件的服务器端值?我不明白你的例子..