【问题标题】:Regular expression to match and replace "${foo}" but not "<c:if test="${foo}" />" in Java在Java中匹配和替换“${foo}”而不是“<c:if test="${foo}" />”的正则表达式
【发布时间】:2013-06-12 17:06:23
【问题描述】:

虽然任何人都会探索this question,但显而易见的问题是,是否有任何可能匹配的正则表达式

${foo}

但不是

<c:if test="${foo}" />

<c:when test="${foo}" />

要将那些独立的${foo} 替换为&lt;c:out value="${foo}" /&gt;,这里foo 可以是任何字符串,只要${foo}jsp 中是有效的el expression

编辑:

${foo} 可以在任何地方,只要它在替换后不违反jsp 语法!这只是防止XXS attackjsp 中的预防措施。

【问题讨论】:

  • 所以只有 ${foo} 但没有 "?
  • ${foo} 在某个其他标签的字符串中时怎么样?
  • 呃等等,这似乎是 JSP;为什么需要解析 JSP?
  • 是的,但仍然:有一个链接会很有趣,或者至少你在帖子中添加了这样一个利用的例子
  • @fge,我用链接编辑了问题。

标签: java regex jsp jakarta-ee replace


【解决方案1】:

说明

此正则表达式将找到不在 &lt;c:.... test="${foo}" /&gt; 块内的裸 ${foo}

正则表达式:(?!("))\$\{[^}]*\}(?!")

替换为&lt;c:out value="$0" /&gt;

输入文字:&lt;c:if test="${foo man chu}" /&gt;${foo bar}more text here

输出文本:&lt;c:if test="${foo man chu}" /&gt;&lt;c:out value="${foo bar}" /&gt;more text here


要处理${foo.bar} 可能位于` 标签内的其他边缘情况,您可能需要使用此正则表达式

正则表达式:(?!("))(\$\{[^}]*\})(?!")|(&lt;a\b[^&gt;]*\bhref=")(\$\{[^}]*\})(")

替换为:$3&lt;c:out value="$1$2$4" /&gt;$5

输入文字:&lt;c:if test="${foo man chu}" /&gt;${foo bar}more &lt;a href="${foo.name}" /&gt;text here

输出文本:&lt;c:if test="${foo man chu}" /&gt;&lt;c:out value="${foo bar}" /&gt;more &lt;a href="&lt;c:out value="${foo.name}" /&gt;" /&gt;text here

【讨论】:

  • 是的,你是对的,你的正则表达式会找到赤裸裸的${foo},但是&lt;a href="${foo.name}" /&gt;这种可替换的${foo}会被忽略。
  • 原始示例文本中未包含该边缘情况。请参阅更新的响应,其中解决了其他极端情况。
【解决方案2】:

以下正则表达式应该适用于您的示例:

\${[^}]*}(?![^<>]*>)

现场演示:http://www.rubular.com/r/ICdR4TGQXu

虽然我认为这对于一些罕见的情况可能仍然会产生误报。

【讨论】:

  • 是的,你是对的,你的表情检测不到&lt;a href="${foo.name}" /&gt;,但还是那么接近!
  • 我已经很久没有写一些 JSTL 了,但是 &lt;a href="${foo.name}" /&gt; 也不会被包裹在一些 &lt;c: ... /&gt; 中。
  • 您宁愿用&lt;a href="${fn:escapeXml(foo.name)}" /&gt; 代替&lt;a href="&lt;c:out value="${foo.name}" /&gt;" /&gt;。所以需要一个不同的正则表达式(或者只是一个不同的替换)。
【解决方案3】:

我相信您可能正在尝试在支持按正则表达式查找功能的文本编辑器中编辑您的 JSP。否则尝试解析您的 JSP(如 @fge 指出的)是不明智的。

这是一个匹配 ${foo} 但不匹配 ="${foo}" 的正则表达式

(?<!=")\${foo}(?!")

有效消除&lt;c:if test="${foo}" /&gt;&lt;c:when test="${foo}" /&gt; 上的匹配

【讨论】:

    【解决方案4】:

    试试这个

    str = str.replaceAll("(?<!<c:(if|when) test=[\"'])\\$\\{foo}", "<c:out value=\"\\${foo}\" />");
    

    【讨论】:

      【解决方案5】:

      一般来说,正则表达式不足以正确处理任何重要的语言,尤其是允许匹配括号、转义引号和嵌套引用的语言。

      您可能会在这里找到一个似乎适用于大多数情况的正则表达式,但这可能只是意味着您还没有遇到足够聪明的攻击者。

      您需要更加严格地限制用户输入的内容。您不应该接受 JSP 代码,尝试“清理它”,然后执行它。你被利用。甚至 Sun 也无法做到这一点(参见:最近针对 Java Applet 沙箱的一系列攻击)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多