每当用户在我的web应用程序中的页面中发布包含<或>的内容时,我都会引发此异常。
我不想因为有人在文本框中输入了字符而引发异常或使整个web应用程序崩溃,但我正在寻找一种优雅的方式来处理这一问题。
捕获异常并显示
出现错误,请返回并重新键入整个表单,但这次请不要使用<
我觉得不够专业。
禁用后验证(validateRequest=“false”)肯定可以避免此错误,但这会使页面容易受到许多攻击。
理想情况下:当发生包含HTML限制字符的回发时,表单集合中的回发值将自动进行HTML编码。因此,我的文本框的.Text属性将是<;html>;
有没有办法让我从处理者那里做到这一点?
最后但同样重要的是,请注意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.文本值:';
TextBox2.文本值:&#39;
案例提交值:<script>alert('attack!')</脚本>
标签1.文本值:<script>alert('attack!')</脚本>
TextBox2.文本值:<;脚本>;警报(';攻击!';)</脚本>;
这里的其他解决方案很好,但必须将[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(),否则不应该需要此功能。
解决方案
我不想关闭后验证(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>