Angenommen, ich habe ein Objekt mit Zeichenfolgenschlüsseln und Zeichenfolgenwerten und möchte diese als benutzerdefinierte CSS-Eigenschaften in einen vom Server generierten HTML-Code schreiben. Wie kann ich das sicher machen?
Was ich mit Sicherheit meine
Der Einfachheit halber beschränke ich die Tasten darauf, nur Zeichen der Klasse [a-zA-Z0-9_-]
zuzulassen.
Nachdem ich die CSS-Spezifikation gelesen und einige persönliche Tests durchgeführt habe, denke ich, dass Sie große Fortschritte machen können, indem Sie die folgenden Schritte befolgen:
{([字符串外部的
außerhalb der Zeichenfolge eine passende schließende Klammer hat. Wenn nicht, verwerfen Sie dieses Schlüssel-Wert-Paar. 3C
转义 <
的所有实例,以及使用 3E
转义 >
. 3B
对 ;
, um zu entkommen. Ich habe mir die oben genannten Schritte basierend auf dieser CSS-Syntaxspezifikation ausgedacht
Für den Kontext können diese Eigenschaften von benutzerdefinierten Stilen verwendet werden, die wir an anderer Stelle einfügen. Das gleiche Objekt wird jedoch auch als Vorlagendaten in der Vorlage verwendet, sodass es eine Mischung aus Zeichenfolgen enthalten kann, die als Inhalt gedacht sind, und Zeichenfolgen, die als CSS-Variablen erwartet werden . Ich habe das Gefühl, dass der obige Algorithmus eine gute Balance zwischen Einfachheit schafft, ohne das Risiko einzugehen, zu viele Schlüssel-Wert-Paare wegzuwerfen, die in CSS nützlich sein könnten (und sogar zukünftige Ergänzungen zu CSS zu ermöglichen, aber ich möchte sicherstellen, dass ich das nicht tue). Es fehlt nichts
Hier ist ein JS-Code, der zeigt, was ich erreichen möchte. obj
是有问题的对象,而 preprocessPairs
ist eine Funktion, die das Objekt nimmt und es vorverarbeitet, wobei die Werte wie in den obigen Schritten beschrieben entfernt/neu formatiert werden.
function generateThemePropertiesTag(obj) { obj = preprocessPairs(obj); return `<style> :root { ${Object.entries(obj).map(([key, value]) => { return `--theme-${key}: ${value};` }).join("\n")} } </style>` }
Wenn man also ein Objekt wie dieses erhält
{ "color": "#D3A", "title": "The quick brown fox" }
Ich möchte, dass das CSS so aussieht:
:root { --theme-color: #D3A; --theme-title: The quick brown fox; }
Obwohl --theme-title
eine ziemlich nutzlose benutzerdefinierte Variable ist, wenn sie in CSS verwendet wird, beschädigt sie das Stylesheet nicht wirklich, da CSS Eigenschaften ignoriert, die es nicht versteht.
我们实际上可能只使用正则表达式和一些其他算法,而不必依赖于一种特定的语言,希望这是您所需要的。
通过声明对象键位于
[a-zA-Z0-9_-]
内,我们需要以某种方式解析值。价值模式
因此,我们可以将其分为几类,然后看看我们会遇到什么(为了清楚起见,它们可能会稍微简化):
'.*'
(用撇号包围的字符串;贪婪)".*"
(用双引号括起来的字符串;贪婪)[+-]?\d+(\.\d+)?(%|[A-z]+)?
(整数和小数,可选百分比或带单位)#[0-9A-f]{3,6}
(颜色)[A-z0-9_-]+
(关键字、命名颜色、“缓入”等内容)([\w-]+)\([^)]+\)
(类似url()
、calc()
的函数> 等等)第一次过滤
我可以想象在尝试识别这些模式之前您可以进行一些过滤。也许我们首先修剪值字符串。正如您所提到的,
和
>
可以在preprocessPairs()
函数的开头进行转义,因为它不会出现为我们上面有的任何模式。如果您不希望在任何地方出现未转义的分号,您也可以转义它们。识别模式
然后我们可以尝试识别值中的这些模式,对于每个模式,我们可能需要再次运行过滤。我们期望这些模式将由一些(或两个)空白字符分隔。
包括对多行字符串的支持应该没问题,这是一个转义的换行符。
语言环境
我们需要认识到我们至少要过滤两个上下文 - HTML 和 CSS。当我们在
元素中包含样式时,输入必须是安全的,同时它必须是有效的 CSS。幸运的是,您没有将 CSS 包含在元素的
style
属性中,因此这会稍微容易一些。基于值模式的过滤
因此第 1-5 点将非常简单,通过前面的简单过滤和修剪将覆盖大部分值。通过一些添加(不知道对性能有什么影响),它甚至可能会对正确的单位、关键字等进行额外的检查。
但与其他点相比,我认为相对更大的挑战是第 6 点。您可能决定简单地禁止此自定义样式中的
url()
,让您检查函数的输入,因此例如您可能想要转义分号,甚至可能通过微小的调整再次检查函数内的模式例如对于calc()
。结论
总的来说,这是我的观点。通过对这些正则表达式进行一些调整,它应该能够补充您已经所做的工作,并为输入 CSS 提供尽可能多的灵活性,同时使您不必在每次调整 CSS 功能时都调整代码。
示例
请评论、讨论、批评,如果我忘记触及您特别感兴趣的某个话题,请告诉我。
来源
免责声明:我不是以下提到的来源的作者、所有者、投资者或贡献者。我只是碰巧用它们来获取一些信息。