2008-10-15 29 views
19

¿Alguien tiene una manera simple y eficiente de verificar que una cadena no contenga HTML? Básicamente, quiero verificar que ciertos campos solo contengan texto sin formato. Pensé en buscar el carácter <, pero eso se puede usar fácilmente en texto plano. Otra forma podría ser la creación de un nuevo System.Xml.Linq.XElement usando:Cómo validar que una cadena no contiene HTML utilizando C#

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

y comprobar que el XElement no contiene elementos secundarios, pero esto parece un poco pesado para lo que necesito.

+0

Para hacer esto, usted está probablemente va a tener que definir lo que entendemos por "HTML" y "texto plano", por ejemplo: ¿Va a permitir que alguien puso "" en el texto sin formato, que parece * como * un elemento HTML pero no lo es, y también, ¿qué caracteres permitirá? – Rob

+0

En mi caso, estoy bien diciendo que no hay etiquetas, por lo que no estaría permitido. Mis usuarios son un número limitado de empleados que ingresan productos en el sitio web de nuestra compañía. Han empezado a abusar un poco de los campos e incluyen HTML en campos que no fueron diseñados para contener HTML. –

Respuesta

6

simplemente he intentado mi solución XElement.Parse. He creado un método de extensión de la clase string para que pueda volver a utilizar el código fácilmente:

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

Un problema que encontré fue que signo texto plano y menos de caracteres provocan un XmlException e indican que el campo contiene HTML (que es incorrecto). Para solucionar esto, la cadena de entrada que se pasa primero debe tener los signos de unión y menos de caracteres convertidos a sus entidades XHTML equivalentes.Escribí otro método de extensión para hacer eso:

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

Ahora puede tomar una cadena enviado por el usuario y comprobar que no contiene HTML usando el siguiente código:

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

No estoy seguro si esto es a prueba de balas, pero creo que es lo suficientemente bueno para mi situación.

+0

Asegúrate de que no contenga XHTML. No está verificando para asegurarse de que no contenga HTML, que no tiene que ser un XML bien formado. Además, su código no detectará "esto es XHTML". –

+0

En realidad, el HTML de estilo antiguo que no está bien formado XML hará que el método XElement.Parse falle. Mi método asume que el método Parse falla significa que la cadena contiene alguna forma de HTML. Supongo que mi código realmente busca cualquier tipo de etiqueta. –

+0

también podemos usar regex patten, para verificar las etiquetas de apertura de cierre. – bijayk

44

Lo siguiente coincidirá con cualquier conjunto de etiquetas coincidentes. es decir < b> esta </b>

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

El siguiente coincidirá con cualquier etiqueta única. es decir, < b> (no tiene que estar cerrado).

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

entonces Se puede utilizar como tal

bool hasTags = tagRegex.IsMatch(myString); 
8

Aquí van:

using System.Text.RegularExpressions; 
private bool ContainsHTML(string CheckString) 
{ 
    return Regex.IsMatch(CheckString, "<(.|\n)*?>"); 
} 

Esa es la forma más sencilla, ya que los elementos entre corchetes son poco probable que se produzca de forma natural.

2

Los soportes angulares pueden no ser su único desafío. Otros caracteres también pueden ser inyecciones de script potencialmente dañinas. Como el doble guión común "-", que también se puede usar en inyección SQL. Y hay otros.

En una página ASP.Net, si validateRequest = true en machine.config, web.config o la directiva de página, el usuario obtendrá una página de error que indica "Se detectó un valor potencialmente potencialmente peligroso Request.Form del cliente" si se detecta una etiqueta HTML u otros posibles ataques de inyección de scripts. Probablemente desee evitar esto y proporcionar una experiencia de IU más elegante y menos atemorizante.

Puede probar las etiquetas de apertura y cierre <> utilizando una expresión regular, y permitir el texto si solo aparece una de ellas. Permitir < o>, pero no < seguido de texto y luego>, en ese orden.

Puede permitir los corchetes angulares y HtmlEncode el texto para conservarlos cuando los datos se mantienen.

+0

Si su estrategia para lidiar con la inyección de SQL está eliminando "-" la entrada, tiene un problema mayor. –

+1

Excelente punto, Robert, pero no creo que este sea el lugar para lanzar una explicación completa de la defensa contra la inyección de SQL u otras técnicas de inyección de scripts. Mi primera línea de defensa contra la inyección SQL es el uso de SQL parametrizado. ¿Lo que es tuyo? – DOK

20

Puede garantizar el texto sin formato codificando la entrada usando HttpUtility.HtmlEncode.

De hecho, dependiendo del grado de rigurosidad desea que el cheque sea, se podría utilizar para determinar si la cadena contiene HTML:

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

¡Una respuesta simple pero efectiva! –

+7

Lamentablemente no funciona si su cadena contiene apóstrofes, símbolos, etc. – PeteG

+0

@PeteG Buen punto, sí, parece que a partir de .NET 4, este método realmente codifica más cosas de lo que solía, como comillas simples. Esto hace que esta técnica sea menos útil. –

0

Tenga cuidado al utilizar el método HttpUtility.HtmlEncode mencionado anteriormente. Si está verificando texto con caracteres especiales, pero no HTML, se evaluará incorrectamente. Tal vez es por eso que J c usó "... dependiendo de qué tan estricto quieras que sea el cheque ..."

3

esto también comprueba cosas como < br /> etiquetas autocerradas con espacios en blanco opcionales. la lista no contiene nuevas etiquetas 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"); 
    } 
} 
Cuestiones relacionadas