亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

無需 JavaScript 即可安全地將不受信任的輸入指派給 CSS 自訂屬性:指南
P粉356361722
P粉356361722 2023-09-06 22:32:52
0
1
876

假設(shè)我有一個(gè)字串鍵和字串值的對(duì)象,我想將它們作為 CSS 自訂屬性寫入伺服器產(chǎn)生的一些 HTML 中。我怎樣才能安全地做到這一點(diǎn)?

我所說的安全是指

  • 如果可能的話,自訂屬性宣告不應(yīng)導(dǎo)致 CSS 語(yǔ)法錯(cuò)誤,從而阻止瀏覽器正確解析其他樣式宣告或 HTML 文件的部分。如果由於某種原因這是不可能的,則應(yīng)省略鍵值對(duì)。
  • 更重要的是,這樣應(yīng)該不可能進(jìn)行跨站點(diǎn)腳本編寫。

為了簡(jiǎn)單起見,我將限制鍵只允許 [a-zA-Z0-9_-] 類別中的字元。

透過閱讀 CSS 規(guī)範(fàn)和一些個(gè)人測(cè)試,我認(rèn)為透過以下步驟來取得值可以取得很大的進(jìn)展:

  • 查找字串
  • 確保每個(gè)引號(hào)後面都有另一個(gè)相同類型(“或')的(未轉(zhuǎn)義的)引號(hào)。如果不是這種情況,請(qǐng)丟棄此鍵/值對(duì)。
  • 確保字串外部的每個(gè)左大括號(hào) {([字串外部的 都有一個(gè)符合的右大括號(hào)。如果沒有,則丟棄此鍵值對(duì)。
  • 使用 \3C 轉(zhuǎn)義 << 的所有實(shí)例,以及所有使用 3E 轉(zhuǎn)義 > 的所有實(shí)例。
  • 使用 \3B 對(duì) ; 的所有實(shí)例進(jìn)行轉(zhuǎn)義。

我根據(jù)這個(gè) CSS 語(yǔ)法規(guī)格想出了上述步驟

對(duì)於上下文,這些屬性可以由我們?cè)谄渌胤讲迦氲挠脩糇杂啒邮绞褂?,但同一物件也用作模板中的模板?shù)據(jù),因此它可能包含旨在作為內(nèi)容的字串和預(yù)期的字串的混合作為CSS 變數(shù)。我覺得上面的演算法取得了很好的平衡,既非常簡(jiǎn)單,又不會(huì)冒丟棄太多可能在CSS 中有用的鍵值對(duì)的風(fēng)險(xiǎn)(即使考慮到未來對(duì)CSS 的添加,但我想確保我沒有遺漏什麼。


這裡有一些 JS 程式碼,展示了我想要實(shí)現(xiàn)的目標(biāo)。 obj 是有問題的對(duì)象,而 preprocessPairs 是一個(gè)函數(shù),它接受該對(duì)象並對(duì)其進(jìn)行預(yù)處理,刪除/重新格式化值,如上述步驟所述。

function generateThemePropertiesTag(obj) {
  obj = preprocessPairs(obj);
  return `<style>
:root {
${Object.entries(obj).map(([key, value]) => {
  return `--theme-${key}: ${value};`
}).join("\n")}
}
</style>`
}

所以當(dāng)給定一個(gè)這樣的物件時(shí)

{
  "color": "#D3A",
  "title": "The quick brown fox"
}

我希望 CSS 看起來像這樣:

:root {
--theme-color: #D3A;
--theme-title: The quick brown fox;
}

雖然 --theme-title 在 CSS 中使用時(shí)是一個(gè)非常無用的自訂變量,但它實(shí)際上並沒有破壞樣式表,因?yàn)?CSS 會(huì)忽略它不理解的屬性。

P粉356361722
P粉356361722

全部回覆(1)
P粉898107874

我們實(shí)際上可能只使用正規(guī)表示式和一些其他演算法,而不必依賴特定的語(yǔ)言,希望這是您所需要的。

透過宣告物件鍵位於 [a-zA-Z0-9_-] 內(nèi),我們需要以某種方式解析值。

價(jià)值模式

因此,我們可以將其分為幾類,然後看看我們會(huì)遇到什麼(為了清楚起見,它們可能會(huì)稍微簡(jiǎn)化):

  1. '.*'(用撇號(hào)包圍的字串;貪婪)
  2. ".*"(用雙引號(hào)括起來的字串;貪婪)
  3. [ -]?\d (\.\d )?(%|[A-z] )?(整數(shù)和小數(shù),可選百分比或帶單位)
  4. #[0-9A-f]{3,6}(顏色)
  5. [A-z0-9_-] (關(guān)鍵字、命名顏色、「緩入」等內(nèi)容)
  6. ([\w-] )\([^)] \) (類似url()、calc() 的函數(shù)> 等等)

第一次過濾

我可以想像在嘗試識(shí)別這些模式之前您可以進(jìn)行一些過濾。也許我們首先修剪值字串。正如您所提到的, > 可以在preprocessPairs() 函數(shù)的開頭進(jìn)行轉(zhuǎn)義,因?yàn)樗粫?huì)出現(xiàn)為我們上面有的任何模式。如果您不希望在任何地方出現(xiàn)未轉(zhuǎn)義的分號(hào),您也可以轉(zhuǎn)義它們。

識(shí)別模式

然後我們可以嘗試識(shí)別中的這些模式,對(duì)於每個(gè)模式,我們可能需要再次執(zhí)行過濾。我們期望這些模式將由一些(或兩個(gè))空白字元分隔。

包括對(duì)多行字串的支援應(yīng)該沒問題,這是一個(gè)轉(zhuǎn)義的換行符。

語(yǔ)言環(huán)境

我們需要認(rèn)識(shí)到我們至少要過濾兩個(gè)上下文 - HTML 和 CSS。當(dāng)我們?cè)? 元素中包含樣式時(shí),輸入必須是安全的,同時(shí)它必須是有效的 CSS。幸運(yùn)的是,您沒有將 CSS 包含在元素的 style 屬性中,因此這會(huì)稍微容易一些。

基於值模式的篩選

  1. 由撇號(hào)包圍的字串- 除了撇號(hào)和分號(hào)之外我們不關(guān)心任何東西,因此我們需要在字串中找到這些字元的未轉(zhuǎn)義實(shí)例並對(duì)它們進(jìn)行轉(zhuǎn)義
  2. 同上,只是用雙引號(hào)
  3. 應(yīng)該沒問題
  4. 應(yīng)該沒問題
  5. 基本沒問題
  6. 這是有趣的部分

因此第 1-5 點(diǎn)將非常簡(jiǎn)單,透過前面的簡(jiǎn)單過濾和修剪將覆蓋大部分值。透過一些添加(不知道對(duì)效能有什麼影響),它甚至可能會(huì)對(duì)正確的單位、關(guān)鍵字等進(jìn)行額外的檢查。

但與其他點(diǎn)相比,我認(rèn)為相對(duì)更大的挑戰(zhàn)是第 6 點(diǎn)。您可能決定簡(jiǎn)單地禁止此自訂樣式中的url() ,讓您檢查函數(shù)的輸入,因此例如您可能想要轉(zhuǎn)義分號(hào),甚至可能透過微小的調(diào)整再次檢查函數(shù)內(nèi)的模式例如對(duì)於calc()。

結(jié)論

總的來說,這是我的觀點(diǎn)。透過對(duì)這些正規(guī)表示式進(jìn)行一些調(diào)整,它應(yīng)該能夠補(bǔ)充您已經(jīng)所做的工作,並為輸入 CSS 提供盡可能多的靈活性,同時(shí)使您不必在每次調(diào)整 CSS 功能時(shí)調(diào)整程式碼。

範(fàn)例

function preprocessPairs(obj) {
  // Catch-all regular expression
  // Explanation:
  // (                                   Start of alternatives
  //   \w+\(.+?\)|                       1st alternative - function
  //   ".+?(?<!\)"|                     2nd alternative - string with double quotes
  //   '.+?(?<!\)'|                     3rd alternative - string with apostrophes
  //   [+-]?\d+(?:\.\d+)?(?:%|[A-z]+)?|  4th alternative - integer/decimal number, optionally per cent or with a unit
  //   #[0-9A-f]{3,6}|                   5th alternative - colour
  //   [A-z0-9_-]+|                      6th alternative - keyword
  //   ''|                               7th alternative - empty string
  //   ""                                8th alternative - empty string
  // )
  // [\s,]*
  const regexA = /(\w+\(.+?\)|".+?(?<!\)"|'.+?(?<!\)'|[+-]?\d+(?:\.\d+)?(?:%|[A-z]+)?|#[0-9A-f]{3,6}|[A-z0-9_-]+|''|"")[\s,]*/g;

  // newObj contains filtered testObject
  const newObj = {};

  // Loop through all object properties
  Object.entries(obj).forEach(([key, value]) => {
    // Replace <>;
    value = value.trim().replace('<', '\00003C').replace('>', '\00003E').replace(';', '\00003B');

    // Use catch-all regex to split value into specific elements
    const matches = [...value.matchAll(regexA)];

    // Now try to build back the original value string from regex matches.
    // If these strings are equal, the value is what we expected.
    // Otherwise it contained some unexpected markup or elements and should
    // be therefore discarded.
    // We specifically set to ignore all occurences of url() and @import
    let buildBack = '';
    matches.forEach((match) => {
      if (Array.isArray(match) && match.length >= 2 && match[0].match(/url\(.+?\)/gi) === null && match[0].match(/@import/gi) === null) {
        buildBack += match[0];
      }
    });

    console.log('Compare\n');
    console.log(value);
    console.log(buildBack);
    console.log(value === buildBack);

    if (value === buildBack) {
      newObj[key] = value;
    }
  });

  return newObj;
}

請(qǐng)?jiān)u論、討論、批評(píng),如果我忘記觸及您特別感興趣的某個(gè)主題,請(qǐng)告訴我。

來源

免責(zé)聲明:我不是以下提到的來源的作者、所有者、投資者或貢獻(xiàn)者。我只是碰巧用它們來獲取一些資訊。

###
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板