用于编码HTML的正则表达式
我想创建一个正则表达式,该正则表达式将匹配只包含href属性的开头用于编码HTML的正则表达式,html,regex,validation,sanitization,html-encode,Html,Regex,Validation,Sanitization,Html Encode,我想创建一个正则表达式,该正则表达式将匹配只包含href属性的开头标记: <a href="doesntmatter.com"> 但与此不符: <a href="doesntmatter.com" > <a href="doesntmatter.com" onmouseover="alert(
标记:
<a href="doesntmatter.com">
但与此不符:
<a href="doesntmatter.com" >
<a href="doesntmatter.com" onmouseover="alert('do something evil with javascript.')" >
假设所有编码的HTML都是“有效的”(没有奇怪的畸形XSS欺骗),并且假设我们不需要遵循任何HTML净化最佳实践。我只需要最简单的正则表达式,它将匹配上面的A)而不是B)
谢谢 首先想到的正则表达式是
/。原子分组告诉正则表达式引擎,“一旦找到该组的匹配项,就接受它”——这将解决正则表达式在未在href末尾找到a>a后返回并匹配第二个字符串的问题。带有原子组的正则表达式如下所示:
/<a (?>href=".*?")>/
我看不出两者有什么不同?你只是在寻找你刚刚写的东西,把doesntmatter.com
部分变成你所捕获的部分。我猜在"代码>(不是“
?)可能会出现问题,但在正则表达式中是这样做的:
(?:(?!&34;)*
它基本上意味着:
- 匹配以下组0次或更多次
- 如果以下字符串为
”",则匹配失败;“
- 匹配任何字符(新行除外,除非指定了DOTALL)
完整的正则表达式是:
/<a href="(?>(?:[^&]+|(?!").)*)">/s
这比使用非贪婪表达式更有效
感谢Daniel Vandersluis提醒我!为了优化,它非常适合这里(如果必须回溯,则此模式永远无法匹配)
我还加入了一个额外的[^&]+
组,以避免多次重复负面展望
或者,您也可以使用,它基本上做相同的事情(您的正则表达式引擎可能不支持它):
正如你所看到的,它稍微短了一点。嘿!我最近也做了类似的事情。我建议先解码html,然后尝试获取你想要的信息。以下是我的C#解决方案:
私有字符串getAnchor(字符串数据)
{
匹配集合匹配;
字符串模式=@“”;
Regex myRegex=新的Regex(模式,RegexOptions.Multiline);
弦锚=”;
matches=myRegex.matches(数据);
foreach(匹配中的匹配)
{
锚定+=match.Groups[“href”].Value.Trim()+,“+match.Groups[“text”].Value.Trim();
}
回锚;
}
我希望这会有帮助!但是如果我错了,请纠正我:当您使用。*时,即使您使用。*?使其不贪婪,它将捕获所有内容,直到onmouseover属性中的最后一个引号,匹配这两个表达式。这正是我遇到的问题!您是对的;因为表达式末尾的
,r正则表达式引擎将匹配无效的语句,因为从第一个引号到字符串末尾有一个匹配项。这里的解决方案是使用原子组,我将更新我的答案进行解释。啊,是的,使用原子组是一个好主意(我通常使用所有格量词;本质上是一样的)!我把它添加到我的正则表达式中,因为否则它会做很多不必要的回溯。谢谢各位。回答得很好。我不知道现在应该将其中哪一个标记为已回答。:)这就是我要找的-负面展望。谢谢~我对这一点投了赞成票,因为这将是我的第二个解决方案,但我宁愿不必编码/解码,也可能如果HTML具有这些额外属性,请对其重新编码。感谢您的帮助!为什么要对HTML进行编码?它总是十进制字符引用吗?我们允许用户通过注释提交HTML,因此我们使用AntiXS(返回十进制字符引用)对所有内容进行编码,然后使用基于白名单的方法选择性地解码安全内容。
/<a (?>href=".*?")>/
/<a href="(?>(?:[^&]+|(?!").)*)">/s
/<a href="(?:[^&]+|(?!").)*+">/s
private string getAnchor(string data)
{
MatchCollection matches;
string pattern = @"<a.*?href=[""'](?<href>.*?)[""'].*?>(?<text>.*?)</a>";
Regex myRegex = new Regex(pattern, RegexOptions.Multiline);
string anchor = "";
matches = myRegex.Matches(data);
foreach (Match match in matches)
{
anchor += match.Groups["href"].Value.Trim() + "," + match.Groups["text"].Value.Trim();
}
return anchor;
}