欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解React?如何防止?XSS?攻擊論$$typeof?的作用

 更新時(shí)間:2022年07月25日 09:34:51   作者:??runnerdancer?  
這篇文章主要介紹了詳解React?如何防止?XSS?攻擊論$$typeof?的作用,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

JSX

先來簡單復(fù)習(xí)一下 JSX 的基礎(chǔ)知識(shí)。JSX 是React.createElement的語法糖

<div id="container">hello</div>

經(jīng)過 babel 編譯后:

React.createElement(
  "div" /* type */,
  { id: "container" } /* props */,
  "hello" /* children */
);

React.createElement最終返回的結(jié)果就是一個(gè)對象,如下:

{
  type: 'div',
  props: {
    id: 'container',
    children: 'hello',
  },
  key: null,
  ref: null,
  $$typeof: Symbol.for('react.element'),
}

這就是一個(gè) React element 對象。

我們甚至可以在代碼中直接寫 React element 對象,React 照樣能正常渲染我們的內(nèi)容:

render() {
  return (
    <div>
      {{
        $$typeof: Symbol.for('react.element'),
        props: {
          dangerouslySetInnerHTML: {
            __html: '<img src="x" onerror="alert(1)">'
          },
        },
        ref: null,
        type: "div",
      }}
    </div>
  );
}

可以復(fù)制這段代碼本地運(yùn)行一下,可以發(fā)現(xiàn)瀏覽器彈出一個(gè)彈窗,并且img已經(jīng)插入了 dom 中。

這里,$$typeof 的作用是啥?為什么使用 Symbol() 作為值?

在了解之前,我們先來簡單看下 XSS 攻擊

XSS 攻擊

我們經(jīng)常需要構(gòu)造 HTML 字符串并插入到 DOM 中,比如:

const messageEl = document.getElementById("message");
var message = "hello world";
messageEl.innerHTML = "<p>" + message + "</p>";

頁面正常顯示。但是如果我們插入一些惡意代碼,比如:

const messageEl = document.getElementById("message");
var message = '<img src onerror="alert(1)">';
messageEl.innerHTML = "<p>" + message + "</p>";

此時(shí)頁面就會(huì)彈出一個(gè)彈窗,彈窗內(nèi)容顯示為 1

因此,直接使用 innerHTML 插入文本內(nèi)容,存在 XSS 攻擊的風(fēng)險(xiǎn)

防止 XSS 攻擊的方法

為了解決類似的 XSS 攻擊方法,我們可以使用一些安全的 API 添加文本內(nèi)容,比如:

  • 使用 document.createTextNode('hello world') 插入文本節(jié)點(diǎn)。
  • 或者使用 textContent 而不是 innerHTML 設(shè)置文本內(nèi)容。
  • 對于一些特殊字符,比如 <>,我們可以進(jìn)行轉(zhuǎn)義,將其轉(zhuǎn)換為 &#60; 以及 &#62;
  • 對于富文本內(nèi)容,我們可以設(shè)置黑名單,過濾一些屬性,比如 onerror 等。

React 對于文本節(jié)點(diǎn)的處理

React 使用 createTextNode 或者 textContent 設(shè)置文本內(nèi)容。

對于下面的代碼:

render() {
  const { count } = this.state
  return (
    <div onClick={() => this.setState({ count: count + 1})}>
      {count}
    </div>
  );
}

React 在渲染過程中會(huì)調(diào)用setTextContent方法為div節(jié)點(diǎn)設(shè)置內(nèi)容,其中,第一次渲染時(shí),直接設(shè)置div節(jié)點(diǎn)的textContent,第二次或者第二次以后的更新渲染,由于第一次設(shè)置了textContent,因此divfirstChild值存在,是個(gè)文本節(jié)點(diǎn)。此時(shí)直接更新這個(gè)文本節(jié)點(diǎn)的nodeValue即可

var setTextContent = function (node, text) {
  if (text) {
    var firstChild = node.firstChild;
    // 如果當(dāng)前node節(jié)點(diǎn)已經(jīng)設(shè)置過textContent,則firstChild不為空,是個(gè)文本節(jié)點(diǎn)TEXT_NODE
    if (
      firstChild &&
      firstChild === node.lastChild &&
      firstChild.nodeType === TEXT_NODE
    ) {
      firstChild.nodeValue = text;
      return;
    }
  }
  // 第一次渲染,直接設(shè)置textContent
  node.textContent = text;
};

綜上,對于普通的文本節(jié)點(diǎn)來說,由于 React 是采用 textContent 或者 createTextNode 的方式添加的,因此是不會(huì)存在 XSS 攻擊的,即使上面示例中,count 的值為 '<img src="x" onerror="alert(1)">'也不會(huì)有被攻擊的風(fēng)險(xiǎn)

dangerouslySetInnerHTML 處理富文本節(jié)點(diǎn)

有時(shí)候我們確實(shí)需要顯示富文本的內(nèi)容,React 提供了dangerouslySetInnerHTML方便我們顯式的插入富文本內(nèi)容

render() {
  return (
    <div
      id="dangerous"
      dangerouslySetInnerHTML={{ __html: '<img src="x" onerror="alert(1)">' }}
    >
    </div>
  );
}

React 在為 DOM 更新屬性時(shí),會(huì)判斷屬性的key是不是dangerouslySetInnerHTML,如果是的話,調(diào)用setInnerHTML 方法直接給 dom 的innerHTML屬性設(shè)置文本內(nèi)容

function setInitialDOMProperties(
  tag,
  domElement,
  rootContainerElement,
  nextProps
) {
  for (var propKey in nextProps) {
    if (propKey === "dangerouslySetInnerHTML") {
      var nextHtml = nextProp ? nextProp.__html : undefined;
      if (nextHtml != null) {
        setInnerHTML(domElement, nextHtml);
      }
    }
  }
}
var setInnerHTML = function (node, html) {
  node.innerHTML = html;
};

可以看出,React 在處理富文本時(shí),也僅僅是簡單的設(shè)置 DOM 的innerHTML屬性來實(shí)現(xiàn)的。

對于富文本潛在的安全風(fēng)險(xiǎn),交由開發(fā)者自行把控。

$$typeof 的作用

render() {
  const { text } = this.state
  return (
    <div>
      {text}
    </div>
  );
}

假設(shè)這個(gè)text是從后端返回來的,同時(shí)后端允許用戶存儲(chǔ) JSON 對象,如果用戶傳入下面這樣的一個(gè)類似 React element 的對象:

{
  type: "div",
  props: {
    dangerouslySetInnerHTML: {
      __html: '<img src="x" onerror="alert(1)">'
    },
  },
  ref: null
}

別忘了前面說過,我們在 JSX 中直接插入 React element 對象也是能夠正常渲染的。

在這種情況下,在React0.13版本時(shí),這是一個(gè)潛在的XSS攻擊,這個(gè)漏洞源于服務(wù)端。如果攻擊者惡意偽造一個(gè)類似 React element 對象的數(shù)據(jù)返回給前端,React 就會(huì)執(zhí)行惡意代碼。但是 React 可以采取措施預(yù)防這種攻擊。

React0.14版本開始,React 為每個(gè) element 都添加了一個(gè)Symbol標(biāo)志:

{
  $$typeof: Symbol.for('react.element'),
  props: {
    id: 'container'
  },
  ref: null,
  type: "div",
}

這個(gè)行得通,是因?yàn)?JSON 不支持Symbol。因此即使是服務(wù)端有風(fēng)險(xiǎn)漏洞并且返回一個(gè) JSON,這個(gè) JSON 也不會(huì)包含Symbol.for('react.element').,在 Reconcile 階段,React 會(huì)檢查element.$$typeof標(biāo)志是否合法。不合法的話直接報(bào)錯(cuò),React 不能接受對象作為 children

專門使用 Symbol.for() 的好處是, Symbols 在 iframe 和 worker 等環(huán)境之間是全局的。因此,即使在更奇特的條件下,Symbols 也能在不同的應(yīng)用程序之間傳遞受信任的元素。同樣,即使頁面上有多個(gè) React 副本,它們?nèi)匀豢梢?ldquo;同意”有效的 $$typeof 值

如果瀏覽器不支持Symbols,React 使用0xeac7代替

{
  $$typeof: '0xeac7',
}

到此這篇關(guān)于詳解React 如何防止 XSS 攻擊論$$typeof 的作用的文章就介紹到這了,更多相關(guān)React $$typeof 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Can't?perform?a?React?state?update?on?an?unmounted?component報(bào)錯(cuò)解決

    Can't?perform?a?React?state?update?on?an?unmoun

    這篇文章主要為大家介紹了Can't?perform?a?React?state?update?on?an?unmounted?component報(bào)錯(cuò)解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • React路由的history對象的插件history的使用解讀

    React路由的history對象的插件history的使用解讀

    這篇文章主要介紹了React路由的history對象的插件history的使用,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • React實(shí)現(xiàn)文件上傳和斷點(diǎn)續(xù)傳功能的示例代碼

    React實(shí)現(xiàn)文件上傳和斷點(diǎn)續(xù)傳功能的示例代碼

    這篇文章主要為大家詳細(xì)介紹了React實(shí)現(xiàn)文件上傳和斷點(diǎn)續(xù)傳功能的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • React?Hooks的useState、useRef使用小結(jié)

    React?Hooks的useState、useRef使用小結(jié)

    React Hooks 是 React 16.8 版本引入的新特性,useState和useRef是兩個(gè)常用的Hooks,本文主要介紹了React?Hooks的useState、useRef使用,感興趣的可以了解一下
    2024-01-01
  • React中的Hooks進(jìn)階理解教程

    React中的Hooks進(jìn)階理解教程

    這篇文章主要介紹了React中的Hooks進(jìn)階理解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • React如何將組件渲染到指定DOM節(jié)點(diǎn)詳解

    React如何將組件渲染到指定DOM節(jié)點(diǎn)詳解

    這篇文章主要給大家介紹了關(guān)于React如何將組件渲染到指定DOM節(jié)點(diǎn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)下吧。
    2017-09-09
  • React中setState的使用與同步異步的使用

    React中setState的使用與同步異步的使用

    這篇文章主要介紹了React中setState的使用與同步異步的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • React?中在?map()?中使用條件跳出map的方法

    React?中在?map()?中使用條件跳出map的方法

    這篇文章主要介紹了React?中在?map()?中使用條件跳出map的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • react中如何使用監(jiān)聽

    react中如何使用監(jiān)聽

    在 React 中,您可以使用?addEventListener?函數(shù)來監(jiān)聽事件,本文通過實(shí)例代碼給大家介紹react中如何使用監(jiān)聽,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • React如何實(shí)現(xiàn)瀏覽器打印部分內(nèi)容詳析

    React如何實(shí)現(xiàn)瀏覽器打印部分內(nèi)容詳析

    這篇文章主要給大家介紹了關(guān)于利用React如何實(shí)現(xiàn)瀏覽器打印部分內(nèi)容的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用React具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05

最新評論