styled-components 安全性

2020-07-24 16:09 更新

安全性

因為 styled-components 允許使用任意的輸入作為插值使用,我們必須謹(jǐn)慎處理輸入使其無害.使用用戶輸入作為樣式可能導(dǎo)致用戶瀏覽器中的CSS文件被攻擊者替換.

以下這個例子展示了糟糕的輸入導(dǎo)致的 API 被攻擊:

// Oh no! The user has given us a bad URL!
const userInput = '/api/withdraw-funds'

const ArbitraryComponent = styled.div`
  background: url(${userInput});
  /* More styles here... */
`

請一定謹(jǐn)慎處理!這雖然是一個明顯的例子,但是CSS注入可能隱式的發(fā)生并且產(chǎn)生不良影響.有些舊版本的 IE 甚至?xí)?url 聲明中執(zhí)行 JavaScript.

There is an upcoming standard to sanitize CSS from JavaScript有一個即將推出的標(biāo)準(zhǔn),可以用于無害化 JavaScript 中的 CSS, CSS.escape. 這個標(biāo)準(zhǔn)還沒有被瀏覽器很好的支持 .

Existing CSS

如果想將 styled-components 和現(xiàn)有的 CSS 共同使用,有很多實現(xiàn)的細(xì)節(jié)必須注意到.

styled-components 通過類生成實際的樣式表,并通過className prop將這些類附加到響應(yīng)的 DOM 節(jié)點. 運行時它會被注入到 document 的 head 末尾.

Styling normal React components

使用styled(MyComponent) 聲明, MyComponent 卻不接收傳入的 className prop, 則樣式并不會被呈現(xiàn). 為避免這個問題,請確保組件接收 className 并傳遞給 DOM 節(jié)點:

class MyComponent extends React.Component {
  render() {
    // Attach the passed-in className to the DOM node
    return <div className={this.props.className} />
  }
}

對于已存在類名的組件,可以將其余傳入的類合并:

class MyComponent extends React.Component {
  render() {
    // Attach the passed-in className to the DOM node
    return <div className={`some-global-class ${this.props.className}`} />
  }
}

Issues with specificity

將styled-components類與全局類混用,可能會導(dǎo)致出乎意料的結(jié)果.如果一個property在兩個類中被定義且兩個類的優(yōu)先級相同,則后者會覆蓋前者.

// MyComponent.js
const MyComponent = styled.div`background-color: green;`;

// my-component.css
.red-bg {
  background-color: red;
}

// For some reason this component still has a green background,
// even though you're trying to override it with the "red-bg" class!
<MyComponent className="red-bg" />

上述例子中styled-components類的樣式覆蓋了全局類,因為styled-components在運行時向<head>末尾注入樣式.

一種解決方式是提高全局樣式的優(yōu)先級:

/* my-component.css */
.red-bg.red-bg {
  background-color: red;
}

避免與第三方樣式和腳本的沖突

如果在一個不能完全控制的頁面上部署styled-components,可能需要采取措施確保 component styles 不與 host page 上其他樣式?jīng)_突.

常見的問題是優(yōu)先級相同,例如 host page 上持有如下樣式:

body.my-body button {
  padding: 24px;
}

因為其包含一個類名和兩個標(biāo)簽名,它的優(yōu)先級要高于 styled component 生成的一個類名的選擇器:

styled.button`
  padding: 16px;
`

沒有讓 styled component 完全不受 host page 樣式影響的辦法.但是可以通過babel-plugin-styled-components-css-namespace來提高樣式的優(yōu)先級, 通過它可以為 styled components 的類指定一個命名空間. 一個好的命名空間,譬如#my-widget,可以實現(xiàn)styled-components 在 一個 id="my-widget"的容器中渲染, 因為 id 選擇器的優(yōu)先級總是高于類選擇器.

一個罕見的問題是同一頁面上兩個styled-components實例的沖突.通過在 code bundle 中定義 process.env.SC_ATTR 可以避免這個問題. 它將覆蓋 <style> 標(biāo)簽的data-styled屬性, (v3 及以下版本使用 data-styled-components), allowing each styled-components instance to recognize its own tags.


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號