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

时间:2008-09-17 10:58:14

标签: asp.net asp.net-mvc validation html-encode request.form

每次用户在我的网络应用程序的页面中发布包含<>的内容时,都会抛出此异常。

我不想进入关于抛出异常或崩溃整个Web应用程序的智能性的讨论,因为有人在文本框中输入了一个字符,但我正在寻找一种优雅的方法来处理它。

捕获异常并显示

  

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

对我来说似乎不够专业。

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

理想情况:当发回包含HTML限制字符的帖子时,表单集合中的已发布值将自动进行HTML编码。 因此,我的文本框的.Text属性将为something & lt; html & gt;

我有办法从处理程序执行此操作吗?

44 个答案:

答案 0 :(得分:1041)

我认为你是通过尝试对所有发布的数据进行编码来从错误的角度攻击它。

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

此外,“<”本质上并不危险。它在特定的上下文中是危险的:当编写未编码为HTML输出的字符串时(因为XSS)。

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

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

确定您在任何地方进行HTML编码时都会将字符串传递给HTML,然后在validateRequest="false"文件的<%@ Page ... %>指令中设置.aspx(s )。

在.NET 4中,您可能需要做更多的事情。有时需要将<httpRuntime requestValidationMode="2.0" />添加到web.config(reference)。

答案 1 :(得分:489)

如果你使用的是ASP.NET MVC,那么这个错误会有不同的解决方案:

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

答案 2 :(得分:391)

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

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

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

答案 3 :(得分:209)

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

<httpRuntime requestValidationMode="2.0" />

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

requestValidationMode="2.0"

您可以通过指定:

来完全禁用请求验证
validateRequest="false"

答案 4 :(得分:109)

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

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

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

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

答案 5 :(得分:70)

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

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

这仍然会验证除被排除的字段之外的所有字段。关于这一点的好处是你的验证属性仍然验证字段,但你只是没有得到“从客户端检测到一个潜在危险的Request.Form值”例外。

我用它来验证正则表达式。我已经创建了自己的ValidationAttribute来查看正则表达式是否有效。由于正则表达式可以包含看起来像脚本的东西,我应用了上面的代码 - 正则表达式仍在被检查是否有效,但如果它包含脚本或HTML则不会。

答案 6 :(得分:48)

在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) {
    ...
}

答案 7 :(得分:45)

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

答案 8 :(得分:42)

对于MVC,通过添加

忽略输入验证
  

[ValidateInput(假)]

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

答案 9 :(得分:41)

您可以在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

答案 10 :(得分:33)

请记住,某些.NET控件会自动对输出进行HTML编码。例如,在TextBox控件上设置.Text属性将自动对其进行编码。这具体意味着将<转换为&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>输出到您的页面并随后执行,那么必须在这些属性上设置任何内容。

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

答案 11 :(得分:32)

这个问题的答案很简单:

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

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

答案 12 :(得分:27)

在web.config文件中,在标记内插入httpRuntime元素,其属性为requestValidationMode =“2.0”。还要在pages元素中添加validateRequest =“false”属性。

示例:

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

答案 13 :(得分:23)

如果您不想禁用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);")

答案 14 :(得分:20)

似乎没有人提到下面的内容,但它为我解决了这个问题。在任何人说是的之前它是Visual Basic ...哎呀。

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

我不知道是否有任何缺点,但对我来说,这真的很棒。

答案 15 :(得分:18)

另一种解决方案是:

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;
    }
}

答案 16 :(得分:14)

如果您使用的是框架4.0,那么web.config中的条目(&lt; pages validateRequest =“false”/&gt;)

<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" %>

如果您已经拥有类似&lt;%@ Page的内容,那么只需添加其余=&gt; EnableEventValidation="false"%&gt;

我建议不要这样做。

答案 17 :(得分:13)

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

显示友好留言:

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();
    }
}

答案 18 :(得分:12)

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

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

您应该从Microsoft ACE团队中查看更新,更完整的Anti-XSS library,而不是使用Server.HtmlEncode。

答案 19 :(得分:10)

这里的其他解决方案都很不错,但是后面必须将[AllowHtml]应用于每个Model属性,这是一个很大的痛苦,特别是如果你在一个体面的网站上有超过100个模型。

如果像我一样,你想在网站范围内转换这个(恕我直言,相当无意义)功能,你可以覆盖基本控制器中的Execute()方法(如果你还没有基本控制器,我建议你做一个,它们对于应用常用功能非常有用。)

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

只要确保你是HTML编码所有用户输入的视图(无论如何它是带有Razor的ASP.NET MVC 3中的默认行为),所以除非出于某种奇怪的原因你使用的是Html.Raw ()你不应该要求这个功能。

答案 20 :(得分:10)

<强>原因

默认情况下,ASP.NET会验证可能导致cross-site scripting(XSS)和SQL injections的潜在不安全内容的所有输入控件。因此,通过抛出上述异常,它不允许这样的内容。默认情况下,建议允许在每次回发时进行此检查。

<强>解决方案

在许多情况下,您需要通过Rich TextBoxes或Rich Text Editors向页面提交HTML内容。在这种情况下,您可以通过将@Page指令中的ValidateRequest标记设置为false来避免此异常。

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

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

<pages validateRequest ="false" />

对于.NET 4.0或更高版本的框架,您还需要在&lt; system.web&gt;中添加以下行。以上工作的部分。

<httpRuntime requestValidationMode = "2.0" />

就是这样。我希望这可以帮助你摆脱上述问题。

参考: ASP.Net Error: A potentially dangerous Request.Form value was detected from the client

答案 21 :(得分:10)

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

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

        function boo(){         targetText = document.getElementById(“HiddenField1”);         sourceText = document.getElementById(“userbox”);         targetText.value = escape(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发布,他们只会看到错误。您也可以保存在数据库中编码的所有这些数据,然后将其转发(在服务器端),并解析&amp;在显示在其他地方之前检查攻击。

答案 22 :(得分:9)

我也遇到了这个错误。

就我而言,用户在角色名称中输入了带重音符的字符á(关于ASP.NET成员资格提供者)。

我将角色名称传递给一个方法,以便将用户授予该角色,并且$.ajax帖子请求失败了......

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

而不是

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

这样做

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

@Html.Raw成功了。

我将角色名称视为HTML值roleName="Cadastro b&#225;s"。 ASP.NET MVC阻止了HTML实体&#225;的这个值。现在我按照它应该的方式得到roleName参数值:roleName="Cadastro Básico"并且ASP.NET MVC引擎不再阻止请求。

答案 23 :(得分:9)

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

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

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

答案 24 :(得分:7)

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

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

答案 25 :(得分:6)

我最终在每次回发之前使用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;
}

当然,我的页面主要是数据输入,并且返回的元素很少,但至少保留了他们的数据。

答案 26 :(得分:4)

如果您只想告诉您的用户&lt;和&gt;是不是要使用但是,你不希望整个表格被处理/回发(并且丢失所有输入)之前你不能简单地在场外放置一个验证器来筛选那些(也许是其他有潜在危险的)人物?

答案 27 :(得分:4)

您可以使用以下内容:

var nvc = Request.Unvalidated().Form;

稍后,nvc["yourKey"]应该有效。

答案 28 :(得分:4)

只要 “&lt;”和“&gt;” (而不是双引号本身)字符,你在&lt; input value =“ this ”/&gt;这样的上下文中使用它们,你是安全的(而对于&lt; textarea&gt; 这一个&lt; / textarea&gt;当然你会很脆弱)。这可能会简化您的情况,但对于任何事情,更多地使用其他发布的解决方案。

答案 29 :(得分:4)

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

答案 30 :(得分:3)

您可以在自定义模型Binder中自动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;
        }
    }
}

ErrorController:

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

答案 31 :(得分:2)

对于那些不使用模型绑定的人,他们是从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之间的区别

答案 32 :(得分:2)

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

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

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

答案 33 :(得分:2)

您应该使用Server.HtmlEncode方法来保护您的网站免受危险输入。

More info here

答案 34 :(得分:2)

正如我对Sel's answer的评论所示,这是我们对自定义请求验证程序的扩展。

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);
    }
}

答案 35 :(得分:1)

对于我们这些仍然坚持使用webforms的人,我发现以下解决方案只允许您在一个字段上禁用验证! (我不想在整个页面中禁用它。)

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,它应该允许所有字符(这非常适合密码字段!)

答案 36 :(得分:1)

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

<强> 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;
  2. Label1.Text值:&#39;

    TextBox2.Text值:&amp;#39;

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

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

答案 37 :(得分:1)

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

var arr = ['<input type="text" name="name" />', '<input type="text" name="name" />', '<input type="text" name="name" />', '<input type="text" name="name" />', '<input type="text" name="name" />', '<input type="text" name="name" />', '<input type="text" name="name" />', '<input type="text" name="name" />', '<input type="text" name="name" />', '<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />','<input type="text" name="name" />'];
$(".submit").click(function() {
    for(var i=0; i < 26; i++) {
      $(".inputs").append(arr[i]);
    }
});

$(".calculate").click(function() {
    for(var i=0; i < arr.length; i++)
    sum=sum + arr[i];
    Average = sum/arr.length;
});

答案 38 :(得分:1)

解决方案

我不想关闭帖子验证(validateRequest =&#34; false&#34;)。另一方面,仅仅因为无辜的用户碰巧键入<x或其他东西而导致应用程序崩溃是不可接受的。

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

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

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

请注意,这样做的目的不是保护系统免受黑客入侵,而是为了保护用户免受糟糕的体验。在服务器上完成的请求验证仍然打开,这是(部分)系统的保护(在能够做到这一点的程度)。

我说的原因&#34;&#34;的一部分这是因为我听说内置请求验证可能还不够,因此可能需要其他补充手段才能获得全面保护。但是,我在这里提出的javascript函数还有 nothing 与保护系统有关。 旨在确保用户不会有糟糕的体验。

你可以在这里试试:

&#13;
&#13;
    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;
      }
    }
&#13;
<form onsubmit="return xssCheckValidates();" >
  Try to type < or &# <br/>
  <input type="text" /><br/>
  <textarea></textarea>
  <input type="submit" value="Send" />
</form>
&#13;
&#13;
&#13;

答案 39 :(得分:1)

在我的情况下,

使用asp:Textbox控件(Asp.net 4.5),而不是为validateRequest="false"设置整个页面 我用

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

在导致异常的文本框中。

答案 40 :(得分:0)

使用Server.HtmlEncode("yourtext");

答案 41 :(得分:0)

我看到有很多关于这个的文章...我没有看到这提到。 这是自.NET Framework 4.5以来可用的

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

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

答案 42 :(得分:0)

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

我从另一个角度解决了这个问题...我已经在使用 Ajax Control Toolkit,所以我能够使用 FilteredTextBoxExtender 来防止这两个字符输入到文本框中。用户复制粘贴文本将得到他们所期望的,减去那些字符。

<asp:TextBox ID="CommentsTextBox" runat="server" TextMode="MultiLine"></asp:TextBox>
<ajaxToolkit:FilteredTextBoxExtender ID="ftbe" runat="server" TargetControlID="CommentsTextBox" filterMode="InvalidChars" InvalidChars="<>" />

答案 43 :(得分:-1)

尝试

  

Server.Encode

  

Server.HtmlDecode     发送和接收时。