Skip to main content
 首页 » 编程设计

c#之使用正则表达式将目标 ="_blank"列入白名单

2024年02月23日28jirigala

我在一个站点上工作,该站点对数据库的输出进行清理,以便允许使用一些 html 标记。它使用 Regex 来清理数据。

目前它允许标准 Google (没有目标的标准 href) 但不允许

<a href="http://www.google.com" target="_blank" title="Google">Google</a> 

代码现在看起来像这样:

private static Regex _tags = new Regex("<[^>]*(>|$)", 
RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled); 
private static Regex _whitelist = new Regex(@" 
^</?(b(lockquote)?|code|d(d|t|l|el)|em|h(1|2|3)|i|kbd|u|li|ol|p(re)?|s(ub|up|trong|trike)?|ul)>$| 
^<(b|h)r\s?/?>$", 
    RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); 
private static Regex _whitelist_a = new Regex(@" 
^<a\s 
href=""(\#\d+|(https?|ftp)://[-a-z0-9+&@#/%?=~_|!:,.;\(\)]+)"" 
(\stitle=""[^""<>]+"")?\s?>$| 
^</a>$", 
    RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); 
private static Regex _whitelist_img = new Regex(@" 
^<img\s 
src=""https?://[-a-z0-9+&@#/%?=~_|!:,.;\(\)]+"" 
(\swidth=""\d{1,3}"")? 
(\sheight=""\d{1,3}"")? 
(\salt=""[^""<>]*"")? 
(\stitle=""[^""<>]*"")? 
\s?/?>$", 
    RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); 
 
 
/// <summary> 
/// sanitize any potentially dangerous tags from the provided raw HTML input using  
/// a whitelist based approach, leaving the "safe" HTML tags 
/// CODESNIPPET:4100A61A-1711-4366-B0B0-144D1179A937 
/// </summary> 
public static string Sanitize(string html) 
{ 
    if (String.IsNullOrEmpty(html)) return html; 
 
    string tagname; 
    Match tag; 
 
    // match every HTML tag in the input 
    MatchCollection tags = _tags.Matches(html); 
    for (int i = tags.Count - 1; i > -1; i--) 
    { 
        tag = tags[i]; 
        tagname = tag.Value.ToLowerInvariant(); 
 
        if (!(_whitelist.IsMatch(tagname) || _whitelist_a.IsMatch(tagname) || _whitelist_img.IsMatch(tagname))) 
        { 
            html = html.Remove(tag.Index, tag.Length); 
 
        } 
    } 
 
    return html; 
} 

我也想允许带有目标的 href。

任何帮助都将非常有用,谢谢。

请您参考如下方法:

编辑以在评论中包含第二个请求。

改变:

private static Regex _whitelist_a = new Regex(@" 
^<a\s 
href=""(\#\d+|(https?|ftp)://[-a-z0-9+&@#/%?=~_|!:,.;\(\)]+)"" 
(\stitle=""[^""<>]+"")?\s?>$| 
^</a>$", 
RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); 

到:

private static Regex _whitelist_a = new Regex(@" 
^<a(\starget=""[^""<>]+"")?\s 
href=""(\#\d+|(https?|ftp)://[-a-z0-9+&@#/%?=~_|!:,.;\(\)]+)"" 
(\starget=""[^""<>]+"")?(\stitle=""[^""<>]+"")?\s?>$| 
^</a>$", 
RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); 

这不一定是完美的解决方案,但这将允许在“href”之前和之后的“目标”,或者之前、之后,或者根本没有。

您应该能够创建一个更简洁的正则表达式,类似于:

^<a(\s+(?:target|href|title)="[^"<>]+")*\s*>$|^</a>$ 

但我不确切知道您将如何在您的代码中编写此代码,因为我不熟悉 C# 或 .Net。但您可以尝试以下操作:

private static Regex _whitelist_a = new Regex( 
    @"^<a(\s+(?:target|href|title)=""[^""<>]+"")*\s*>$|^</a>$", 
    RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace 
); 

与上述解决方案相比,此解决方案的优势在于它允许以任何顺序排列任何 href、target 和 title,并且它们之间有任意数量的空格。