我需要从字符串中剥离所有script
标签,但要保留style
。
如果我清理此字符串的style
:
getSanitized(s: string) {
const safeStyle: any = this.sanitizer.bypassSecurityTrustStyle(s);
return safeStyle.changingThisBreaksApplicationSecurity;
}
const s = '<span style="font-size:18px;color:blue">This is a title</span>';
console.log(this.getSanitized(s));
我得到相同的字符串,因为它只包含样式,而且看起来工作正常。
但是如果字符串包含script
,例如
const s = `<script>alert(1);</script>
<span onclick="javascript:alert(2);"
style="font-size:18px;color:blue">This is a title</span>';`
console.log(this.getSanitized(s));
不会从字符串中消除script
标记和onclick
属性。如果我在style
级进行消毒,为什么不能消除它?
答案 0 :(得分:1)
Angular Sanitizer不会修改传递的HTML内容。它不会从中提取任何内容。您需要手动执行此操作。例如,您可以解析传递的HTML内容,从中删除不必要的代码,然后再次将其序列化为字符串。
我知道htmlparser2软件包可以从HTML构建AST。您可以使用它来解析HTML。要将AST序列化为字符串,可以使用dom-serializer包。
因此,使用这些软件包或类似软件包,您的getSanitized
函数逻辑可能会遵循:
async getSanitized(s: string): Promise<string> {
// 1. make an AST from HTML in a string format
const dom = await this.getAST(s);
// 2. remove unwanted nodes from the AST
const filteredDOM = this.filterJS(dom);
// 3. serialize the AST back to a string
const result: string = serializer(filteredDOM);
return result;
}
getAST
函数仅使用htmlparser2
API从字符串中获取AST:
getAST(s: string): Promise<DomElement[]> {
return new Promise((res, rej) => {
const parser = new Parser(
new DomHandler((err, dom) => {
if (err) {
rej(err);
} else {
res(dom);
}
})
);
parser.write(s);
parser.end();
});
}
filterJS
函数可删除不必要的节点。 AST htmlparser2
生成了一个在线可视化程序:https://astexplorer.net/。您可以轻松查看需要使用哪些条件来过滤节点。 filterJS
函数可以实现为:
filterJS(dom: DomElement[]): DomElement[] {
return dom.reduce((acc, node) => {
if (node.type === 'tag') {
node.attribs = this.filterAttribs(node.attribs);
node.children = this.filterJS(node.children);
}
if (node.type !== 'script') {
acc.push(node);
}
return acc;
}, []);
}
简而言之,它将删除script
标签并调用filterAttribs
函数以从事件处理程序中删除JavaScript。 filterAttribs
函数可以是:
filterAttribs(attribs: { [s: string]: string }) {
return Object.entries(attribs).reduce((acc, [key, value]) => {
if (!key.startsWith('on')) {
acc[key] = value;
}
return acc;
}, {});
}
基本上,它会删除从“ on”开始的属性,即事件处理程序。
serializer
函数是对dom-serializer
库的调用。
不要忘记导入htmlparser2
和dom-serializer
:
import { DomHandler, Parser, DomElement } from 'htmlparser2';
import serializer from 'dom-serializer';
为了获得更好的TypeScript体验,htmlparser2
库使用@types/htmlparser2包提供了类型定义。
您可以在https://stackblitz.com/edit/angular-busvys上找到有效的示例。