Javascript 用HTML等价物替换字符串。除了<;a>;标签
如何替换Javascript 用HTML等价物替换字符串。除了<;a>;标签,javascript,jquery,regex,code-injection,Javascript,Jquery,Regex,Code Injection,如何替换字符串: Hello my name is <a href='/max'>max</a>! <script>alert("DANGEROUS SCRIPT INJECTION");</script> 但是我仍然希望能够有链接 我还研究了通过以下方式防止脚本注入: var html = $(string.bold()); html.find('script').remove(); 但是我希望仍然能够读取脚本标记,而不是将其删除。解决
字符串
:
Hello my name is <a href='/max'>max</a>!
<script>alert("DANGEROUS SCRIPT INJECTION");</script>
但是我仍然希望能够有
链接
我还研究了通过以下方式防止脚本注入:
var html = $(string.bold());
html.find('script').remove();
但是我希望仍然能够读取脚本标记,而不是将其删除。解决此问题的一种方法是使用带有严格的查找模式的正则表达式,该模式只允许非常接近某一格式的锚 假设您只希望允许符合以下示例的链接:
<a href="http://host.domain/path?query#anchor">text</a>
也许其他人对这个子问题有更好的解决方案
这是最后一个字符串。替换:
string.replace(/<(?!a href="https?:\/\/\w[\w.-\/\?#]+">\w+<\/a>|\/a>)/g, '<');
string.replace(/\w+\/a>)/g';
注意:所有这些输入检查必须始终在服务器端进行,在客户端,检查可以简单地绕过,并且尽管进行了检查,您仍会将恶意数据发送到服务器。此代码段应该可以做到这一点。您可以在数组
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 += "<" + html.slice(tagStart + 1, tagEnd) + ">";
} else {
processedHTML += html.slice(tagStart, tagEnd + 1);
}
processingStart = tagEnd + 1;
}
// copy the rest of input which wasn't processed
processedHTML += html.slice(processingStart);
//输入
var html=“你好,我的名字是!alert(‘危险的脚本注入’);”;
var allowedTagNames=[“a”];
//输出
var processedHTML=“”;
var processingStart=0;
//此块查找下一个标记并对其进行处理
while(true){
var tagStart=html.indexOf(“,tagStart”);
如果(tagEnd==-1){break;}
var tagNameStart=tagStart+1;
如果(html[标记名开始]=“/”){
//用于结束标记
++tagNameStart;
}
//我们希望标记名后面有一个空格或>
var tagNameEnd=html.indexOf(“,tagNameStart”);
如果(tagNameEnd==-1 | | tagNameEnd>tagEnd){
tagNameEnd=tagEnd;
}
var tagName=html.slice(标记名开始,标记名结束);
//复制位于此标记和最后一个标记末尾之间的文本
processedHTML+=html.slice(processingStart,tagStart);
if(allowedTagNames.indexOf(标记名)=-1){
processedHTML+=“”+html.slice(tagStart+1,tagEnd)+“”;
}否则{
processedHTML+=html.slice(tagStart、tagEnd+1);
}
processingStart=tagEnd+1;
}
//复制未处理的其余输入
processedHTML+=html.slice(processingStart);
注意:如果标记的属性中有
,则它将不起作用。
例如:
您可以在Regex中使用捕获组和lookarounds来实现这一点
string = string.replace(/<((?!a )[^>]*)>/g, "<$1>").replace(/<\/a>/g, "</a>");
string=string.replace(/]*)>/g,“$1”)。replace(/\/a/g,”);
第一部分替换从
到标记的所有HTML标记(锚定开始标记除外),第二部分替换所有更改的锚定结束标记()从/a
返回到如果您只想替换,最好不要在字符串中使用任何HTML,并具有用于插入链接的预定义格式,与插入链接的方式类似(例如[linktext](http://linkurl.com)
)。这样,字符串中就没有HTML,可以完全控制添加的内容。@RajaprabhuAravindasamy这不是重复的-它从字符串中删除所有HTML。OP希望保留a
元素(可能还有其他元素),您可以使用var newStr=$('',{html:str}).find(':not(a)').replaceWith(function(){return this.outerHTML.replace(//g,'').end().html()
其中str
是原始字符串。也就是说,你肯定有更好的事情要做…@Maximilian,因为我认为这是一个错误,我相信你有更好的事情要做。如果我理解的话,您正在尝试在任何用户输入之后清理数据客户端。但是用户仍然可以发送他想要的任何东西。因此,如果您必须清理某些数据,则必须在服务器端而不是客户端完成。@A.Wolff提供的解决方案不完整,它将允许像
锚点这样的事情以及许多其他有问题的事情,如事件处理程序属性。这将无法防止恶意标记。考虑JavaScript:链接、事件处理程序属性等
<(?!a href="https?:\/\/\w[\w.-\/\?#]+">\w+<\/a>)
<(?!a href="https?:\/\/\w[\w.-\/\?#]+">\w+<\/a>|\/a>)
string.replace(/<(?!a href="https?:\/\/\w[\w.-\/\?#]+">\w+<\/a>|\/a>)/g, '<');
// 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 += "<" + html.slice(tagStart + 1, tagEnd) + ">";
} else {
processedHTML += html.slice(tagStart, tagEnd + 1);
}
processingStart = tagEnd + 1;
}
// copy the rest of input which wasn't processed
processedHTML += html.slice(processingStart);
string = string.replace(/<((?!a )[^>]*)>/g, "<$1>").replace(/<\/a>/g, "</a>");