目录
2.1 何谓 DomSanitizer?何谓 bypassSecurityTrustHtml()?
1.问题
[innerHTML] 和 DomSanitizer 的 bypassSecurityTrustHtml() 搭配使用,导致节点无限重复渲染
// 产生 html代码
render: (row) => {
return `<div> ${row.rankNum) </div>`;
)
// 获取安全 Html代码
getSafeHtml(html): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(html);
}
// html 里使用 innerHTML
<div class="header-td"
[innerHTML]="getSafeHtml(render(row))">
</div>
2.思考
2.1 何谓 DomSanitizer?何谓 bypassSecurityTrustHtml()?
DomSanitizer:通过清理在不同 DOM上下文 中安全使用的值,来防止跨站点脚本安全漏洞(XSS)
bypassSecurityTrustHtml():是 DomSanitizer 下面的一个方法,通过接受 html代码 或 svg图片,将他们转换为安全的值,防止出现报错
使用 innerHTML 的时候,可能会出现报错:WARNING: sanitizing HTML stripped some content (see http://g.co/ng/security#xss).
2.2 回到问题本身进行分析
可能性一:
bypassSecurityTrustHtml() 接收的参数应该是 string
此处的 bypassSecurityTrustHtml() 接受了 render(row),render() 方法返回的是 string
重点来了:render() 这个方法 可能 在 bypassSecurityTrustHtml() 之后执行
就是说 render() 还没有返回数据,bypassSecurityTrustHtml() 直接接收了的 render() 这么个空方法
导致 render() 最终在 bypassSecurityTrustHtml() 内部运行,导致重复渲染
可能性二:
innerHTML 接收到的是 getSafeHtml(render(row)) 函数,而不是一段转换完成的 html代码,导致重复渲染
总结:
[innerHTML]、getSafeHtml()、render() 执行顺序不能确定,导致了重复渲染
3.解决
利用 管道 进行 html 代码安全处理,严格控制各个函数的执行顺序
// 产生 html代码
render: (row) => {
return `<div> ${row.rankNum) </div>`;
)
// 通过定义管道,实现获取安全的 html代码 这个功能
transform(html: string): any {
return this.sanitizer.bypassSecurityTrustHtml(html);
}
// html 里使用 innerHTML
<div class="header-td"
[innerHTML]="render(row) | safeHtml">
</div>
执行顺序:
- 先由 render(row) 生成 html代码
- 再进入管道处理
- 最后交由 [innerHTML] 插入节点