React 虚拟DOM的 $$typeof 属性

2019-11-15  本文已影响0人  隐号骑士

研究React虚拟DOM时尝试打印JSX元素,有个属性不太熟悉


capture.png

其它的都可以理解,但是这个 $$typeof 是啥???

在研究了网上的资料后,得出结论,这是用于防止XSS攻击的一种方式。

JSX中插入HTML结构

在传统前端开发中经常使用HTML字符串拼接然后append的方式向页面中引入HTML结构

但这样的写法在React中好像不可以

const html = '<div>123</div>'

function App(props) {
    return (
        <div className="App">
            {html}
        </div>
    );
}
image.png

原因:React等现代前端lib为了防止XSS攻击,对 < > 等符号做了一层转义,称为 escape

如果真的想插入HTML结构而非文本呢?

dangerouslySetInnerHTML

dangerouslySetInnerHTML 是 React 为浏览器 DOM 提供 innerHTML 的替换方案。

const html = '<div>123</div>'

function App(props) {
    return (
        <div
            className="App"
            dangerouslySetInnerHTML={{ __html: html }}
        >
        </div>
    );
}
image.png

风险?

场景:你的服务器存在一个漏洞,使得用户可以存储任意的JSON对象,但客户端却需要一个 string 类型的值。

// 期望该字段为text但是拿到了JSON
let expectedTextButGotJSON = {
  type: 'div',
  props: {
    dangerouslySetInnerHTML: {
      __html: '<img src onerror="alert(document.cookie)"/>'
    },
  },
  // ...
};

// JSX
<p>
  {expectedTextButGotJSON}
</p>

按照Virtual DOM 的渲染机制(学习React VirtualDom),有风险的节点会直接被渲染到DOM树。

$$typeof

React 0.14版本之后,在渲染节点时,新增了一步校验

首先新增一个常量

var REACT_ELEMENT_TYPE =
  (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
  0xeac7;

如果浏览器支持 Symbol:

生成虚拟DOM对象时,自带属性$$typeof : Symbol.for('react.element')

React渲染时,会做校验:

ReactElement.isValidElement = function (object) {
  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
};

为什么用 Symbol.for 呢?

1 Symbol属性不可存放于JSON中

2 Symbol('react.element') !== Symbol('react.element') 但 Symbol.for('react.element') === Symbol.for('react.element')

上一篇 下一篇

猜你喜欢

热点阅读