如何使用 C# 验证字符串不包含 HTML

Posted

技术标签:

【中文标题】如何使用 C# 验证字符串不包含 HTML【英文标题】:How to validate that a string doesn't contain HTML using C# 【发布时间】:2010-09-17 07:21:42 【问题描述】:

有没有人有一种简单、有效的方法来检查字符串是否不包含 html?基本上,我想检查某些字段是否只包含纯文本。我考虑过寻找

XElement.Parse("<wrapper>" + MyString + "</wrapper>")

并检查 XElement 是否不包含子元素,但这对于我的需要来说似乎有点重量级。

【问题讨论】:

为此,您可能必须定义“HTML”和“纯文本”的含义,例如:您是否允许某人在纯文本,它看起来 一个 HTML 元素,但不是,而且,你将允许哪些字符.. 在我的情况下,我可以说根本没有标签,所以 不会被允许。我的用户是少数将产品输入我们公司网站的员工。他们已经开始滥用这些字段,并在原本不包含 HTML 的字段中包含 HTML。 【参考方案1】:

以下内容将匹配任何匹配的标签集。即这个

Regex tagRegex = new Regex(@"<\s*([^ >]+)[^>]*>.*?<\s*/\s*\1\s*>");

以下将匹配任何单个标签。即 (不必关闭)。

Regex tagRegex = new Regex(@"<[^>]+>");

你可以这样使用它

bool hasTags = tagRegex.IsMatch(myString);

【讨论】:

第二个匹配“a c” 我喜欢第一个,但它不包含重复匹配的情况。例如,像“texttexttexttext”这样的字符串,它只会匹配“texttext”和“text”,忽略重叠的“texttexttext【参考方案2】:

您可以通过使用HttpUtility.HtmlEncode 对输入进行编码来确保纯文本。

实际上,根据您希望检查的严格程度,您可以使用它来确定字符串是否包含 HTML:

bool containsHTML = (myString != HttpUtility.HtmlEncode(myString));

【讨论】:

一个简单但有效的答案! 很遗憾,如果您的字符串包含撇号、& 符号等,则不起作用 @PeteG 好点,是的,从 .NET 4 开始,这种方法实际上编码的东西比以前多,比如单引号。这使得这种技术不太有用。 这表示文本“abcd 【参考方案3】:

给你:

using System.Text.RegularExpressions;
private bool ContainsHTML(string checkString)

  return Regex.IsMatch(checkString, "<(.|\n)*?>");

这是最简单的方法,因为括号中的项目不太可能自然出现。

【讨论】:

括号不可能自然出现?!我不跟。如果有人键入“如果 x 10”,则此正则表达式将捕获“” 然而,在我的示例中没有 HTML。 RegEx 作为 HTML 解析器通常不受欢迎。【参考方案4】:

我刚刚尝试了我的 XElement.Parse 解决方案。我在字符串类上创建了一个扩展方法,这样我就可以轻松地重用代码:

public static bool ContainsXHTML(this string input)

    try
    
        XElement x = XElement.Parse("<wrapper>" + input + "</wrapper>");
        return !(x.DescendantNodes().Count() == 1 && x.DescendantNodes().First().NodeType == XmlNodeType.Text);
    
    catch (XmlException ex)
    
        return true;
    

我发现的一个问题是纯文本 & 和小于字符会导致 XmlException 并指示该字段包含 HTML(这是错误的)。为了解决这个问题,首先传入的输入字符串需要将 & 号和小于号字符转换为其等效的 XHTML 实体。我写了另一个扩展方法来做到这一点:

public static string ConvertXHTMLEntities(this string input)

    // Convert all ampersands to the ampersand entity.
    string output = input;
    output = output.Replace("&amp;", "amp_token");
    output = output.Replace("&", "&amp;");
    output = output.Replace("amp_token", "&amp;");

    // Convert less than to the less than entity (without messing up tags).
    output = output.Replace("< ", "&lt; ");
    return output;

现在我可以使用以下代码获取用户提交的字符串并检查它是否不包含 HTML:

bool ContainsHTML = UserEnteredString.ConvertXHTMLEntities().ContainsXHTML();

我不确定这是否是防弹的,但我认为这对我的情况来说已经足够了。

【讨论】:

您正在检查以确保它不包含 XHTML。您没有检查以确保它不包含 HTML,它不必是格式正确的 XML。此外,您的代码不会捕获“this is XHTML”。 实际上,不是格式良好的 XML 的旧式 HTML 会导致 XElement.Parse 方法失败。我的方法假定 Parse 方法失败意味着字符串包含某种形式的 HTML。我想我的代码真的会寻找任何形式的标签。 我们也可以使用正则表达式模式来检查开始的结束标签。【参考方案5】:

这也检查像 带有可选空格的自封闭标签之类的东西。该列表不包含新的 html5 标签。

internal static class HtmlExts

    public static bool containsHtmlTag(this string text, string tag)
    
        var pattern = @"<\s*" + tag + @"\s*\/?>";
        return Regex.IsMatch(text, pattern, RegexOptions.IgnoreCase);
    

    public static bool containsHtmlTags(this string text, string tags)
    
        var ba = tags.Split('|').Select(x => new tag = x, hastag = text.containsHtmlTag(x)).Where(x => x.hastag);

        return ba.Count() > 0;
    

    public static bool containsHtmlTags(this string text)
    
        return
            text.containsHtmlTags(
                "a|abbr|acronym|address|area|b|base|bdo|big|blockquote|body|br|button|caption|cite|code|col|colgroup|dd|del|dfn|div|dl|DOCTYPE|dt|em|fieldset|form|h1|h2|h3|h4|h5|h6|head|html|hr|i|img|input|ins|kbd|label|legend|li|link|map|meta|noscript|object|ol|optgroup|option|p|param|pre|q|samp|script|select|small|span|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|title|tr|tt|ul|var");
    

【讨论】:

【参考方案6】:

尖括号可能不是您唯一的挑战。其他字符也可能是潜在有害的脚本注入。比如常见的双连字符“--”,也可以用在SQL注入中。还有其他的。

在 ASP.Net 页面上,如果 machine.config、web.config 或 page 指令中的 validateRequest = true,则用户将收到一个错误页面,指出“从客户端检测到潜在危险的 Request.Form 值”,如果检测到 HTML 标记或各种其他潜在的脚本注入攻击。您可能希望避免这种情况,并提供更优雅、不那么可怕的 UI 体验。

您可以使用正则表达式测试开始标签和结束标签 ,如果只有其中一个出现,则允许文本。允许 ,但不允许 ,按此顺序。

您可以允许尖括号和 HtmlEncode 文本以在数据持久保存时保留它们。

【讨论】:

如果您处理 SQL 注入的策略是从输入中去除“--”,那么问题就更大了。 很好,罗伯特,但我不认为这是全面解释防御 SQL 注入或其他脚本注入技术的地方。我对 SQL 注入的第一道防线是使用参数化 SQL。你的是什么?【参考方案7】:

使用上面提到的 HttpUtility.HtmlEncode 方法时要小心。如果您正在检查一些带有特殊字符的文本,而不是 HTML,它将不正确地评估。也许这就是为什么 J c 使用“...取决于您希望检查的严格程度...”

【讨论】:

以上是关于如何使用 C# 验证字符串不包含 HTML的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C# 验证 html 文件?

如何验证用户字符串输入不包含 sql 注入?在Javascript中

如何在 C# 中添加不区分大小写的表单字段验证?

c#如何验证签名JWT?

如何在 C# 中解码 HTML 字符?

在 C# 中具有流畅验证的正则表达式 - 如何在密码中不允许空格和某些特殊字符?