繁体   English   中英

用等效的HTML替换字符串。 除了<a>标签</a>

[英]Replace string with HTML equivalent. Apart from <a> tags

我怎么能去替换一个string

Hello my name is <a href='/max'>max</a>! 
<script>alert("DANGEROUS SCRIPT INJECTION");</script>

Hello my name is <a href='/max'>max</a>! 
&lt;script&gt;alert("DANGEROUS SCRIPT INJECTION");&lt;/script&gt;

我可以轻松地将所有<>替换为&lt; &gt; 有:

string = string.replace(/</g, "&lt;").replace(/>/g, "&gt;");

但我仍然希望能够拥有<a>链接。


我还研究了使用以下方法防止脚本注入:

var html = $(string.bold()); 
html.find('script').remove();

但我希望能够仍然阅读脚本标签而不是删除它们。

解决此问题的一种方法是使用具有严格的后视模式的正则表达式,该模式仅允许非常接近某种格式的锚点。

假设您只想允许完全遵循此示例的链接:

<a href="http://host.domain/path?query#anchor">text</a>

<a href="https://host.domain/path?query#anchor">text</a>

构建一个正则表达式,仅匹配此有效模式后面的“<”字符(负向lookbehind):

<(?!a href="https?:\/\/\w[\w.-\/\?#]+">\w+<\/a>)

与该正则表达式的一个问题是,如果你匹配它的整个字符串时, <仍将匹配关闭a元件( </a>所以如果更换每一比赛用&lt; 毕竟你会破坏锚。

您可以通过附加否定后备替代方案来允许所有结束</a>代码:

<(?!a href="https?:\/\/\w[\w.-\/\?#]+">\w+<\/a>|\/a>)

也许其他人对该子问题有更好的解决方案。

这是最后的string.replace:

string.replace(/<(?!a href="https?:\/\/\w[\w.-\/\?#]+">\w+<\/a>|\/a>)/g, '&lt;');

注意:所有这些输入检查必须始终在服务器端完成 ,在客户端,检查可以简单地避开,并且即使进行检查,您也会将恶意数据发送到您的服务器。

这段代码应该可以解决问题。 您可以在数组allowedTagNames添加要作为HTML标记传递的其他标记名称。

// input
var html = "Hello my name is <a href='/max'>max</a>! <script>alert('DANGEROUS SCRIPT INJECTION');</script>";

var allowedTagNames = ["a"];
// output
var processedHTML = "";

var processingStart = 0;
// this block finds the next tag and processes it
while (true) {
    var tagStart = html.indexOf("<", processingStart);
    if (tagStart === -1) { break; }

    var tagEnd = html.indexOf(">", tagStart);
    if (tagEnd === -1) { break; }

    var tagNameStart = tagStart + 1;
    if (html[tagNameStart] === "/") {
        // for closing tags
        ++tagNameStart;
    }
    // we expect there to be either a whitespace or a > after the tagName
    var tagNameEnd = html.indexOf(" ", tagNameStart);
    if (tagNameEnd === -1 || tagNameEnd > tagEnd) {
        tagNameEnd = tagEnd;
    }

    var tagName = html.slice(tagNameStart, tagNameEnd);
    // copy in text which is between this tag and the end of last tag
    processedHTML += html.slice(processingStart, tagStart);
    if (allowedTagNames.indexOf(tagName) === -1) {
        processedHTML += "&lt;" + html.slice(tagStart + 1, tagEnd) + "&gt;";
    } else {
        processedHTML += html.slice(tagStart, tagEnd + 1);
    }
    processingStart = tagEnd + 1;
}
// copy the rest of input which wasn't processed
processedHTML += html.slice(processingStart);

注意:如果标签的属性中有<> ,它将无法工作。 例如: <a href=">">

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM