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

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

捕获异常并显示

出现错误,请返回并重新键入整个表单,但这次请不要使用<

我觉得不够专业。

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

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

有没有办法让我从处理者那里做到这一点?


当前回答

解决方案

我不想关闭后验证(validateRequest=“false”)。另一方面,应用程序崩溃是不可接受的,因为一个无辜的用户碰巧键入了<x或其他内容。

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

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

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

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

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

你可以在这里试试:

函数xssCheckValidates(){var有效=真;var inp=document.querySelectorAll(“输入:not(:禁用):not([readonly]):not([type=hidden])”+“,textarea:not(:禁用):not([readonly])”);对于(变量i=0;i<inp.length;i++){if(!inp[i].readOnly){如果(inp[i].value.indexOf('<')>-1){有效=假;打破}如果(inp[i].value.indexOf('&#')>-1){有效=假;打破}}}if(有效){返回true;}其他{alert('在一个或多个文本字段中,您键入了\r\n字符“<”或字符序列“&#”。\r\n\r\n遗憾的是,这是不允许的,因为它可用于黑客尝试。\r\n\r\n请编辑字段并重试。');return false;}}<form onsubmit=“return xssCheckValidates();”>尝试键入<或&#<br/><input-type=“text”/><br/><textarea></textarea><input-type=“submit”value=“Send”/></form>

其他回答

在我的例子中,使用asp:Textbox控件(asp.net4.5),而不是设置validateRequest=“false”的所有页面我用过

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

在导致异常的文本框上。

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

这里的其他解决方案很好,但必须将[AllowHtml]应用于每个Model属性,特别是如果您在一个规模适中的网站上拥有超过100个模型,这有点麻烦。

如果像我一样,你想在整个站点范围内关闭这个(IMHO非常无意义)功能,你可以在基本控制器中重写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(),否则不应该需要此功能。

最后但同样重要的是,请注意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; }
}

案例提交值:&#39;

标签1.文本值:&#39;

TextBox2.文本值:&amp#39;

案例提交值:<script>alert('attack!')</脚本>

标签1.文本值:<script>alert('attack!')</脚本>

TextBox2.文本值:&lt;脚本&gt;警报(&#39;攻击!&#39;)&lt/脚本&gt;

请记住,某些.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>被输出到页面并随后执行。

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