Supposons que j'ai un objet de clés de chaîne et de valeurs de chaîne et que je souhaite les écrire en tant que propriétés personnalisées CSS dans du HTML généré par le serveur. Comment puis-je le faire en toute sécurité ?
Ce que j'entends par sécurité
Pour plus de simplicité, je limiterai les clés pour autoriser uniquement les caractères de la classe [a-zA-Z0-9_-]
.
En lisant la spécification CSS et en effectuant quelques tests personnels, je pense que vous pouvez faire beaucoup de progrès pour obtenir la valeur en suivant ces étapes :
{([字符串外部的
à l'extérieur de la chaîne a une accolade fermante correspondante. Sinon, supprimez cette paire clé-valeur. 3C
转义 <
的所有实例,以及使用 3E
转义 >
. 3B
对 ;
pour vous échapper. J'ai proposé les étapes ci-dessus sur la base de cette spécification de syntaxe CSS
Pour le contexte, ces propriétés peuvent être utilisées par des styles définis par l'utilisateur que nous insérons ailleurs, mais le même objet est également utilisé comme données de modèle dans le modèle, il peut donc contenir un mélange de chaînes destinées au contenu et de chaînes attendues comme variables CSS. . J'ai l'impression que l'algorithme ci-dessus trouve un bon équilibre entre être très simple sans courir le risque de jeter trop de paires clé-valeur qui pourraient être utiles en CSS (même en permettant de futurs ajouts à CSS, mais je veux m'assurer de ne pas le faire). il ne manque rien
Voici un code JS montrant ce que je veux réaliser. obj
是有问题的对象,而 preprocessPairs
est une fonction qui prend l'objet et le prétraite, en supprimant/reformatant les valeurs comme décrit dans les étapes ci-dessus.
function generateThemePropertiesTag(obj) { obj = preprocessPairs(obj); return `<style> :root { ${Object.entries(obj).map(([key, value]) => { return `--theme-${key}: ${value};` }).join("\n")} } </style>` }
Alors quand on lui donne un objet comme celui-ci
{ "color": "#D3A", "title": "The quick brown fox" }
Je veux que le CSS ressemble à ceci :
:root { --theme-color: #D3A; --theme-title: The quick brown fox; }
Bien que --theme-title
soit une variable personnalisée assez inutile lorsqu'elle est utilisée en CSS, elle ne casse pas réellement la feuille de style car CSS ignore les propriétés qu'il ne comprend pas.
Nous pourrions en fait simplement utiliser des expressions régulières et d'autres algorithmes sans avoir à nous appuyer sur un langage spécifique, j'espère que c'est ce dont vous avez besoin.
En déclarant que la clé de l'objet est à l'intérieur
[a-zA-Z0-9_-]
, nous devons analyser la valeur d'une manière ou d'une autre.Modèle de valeur
Nous pouvons donc le diviser en catégories et voir ce que nous rencontrons (elles peuvent être légèrement simplifiées pour plus de clarté) :
'.*'
(chaîne entourée d'apostrophes ; gourmand)".*"
(Chaîne entre guillemets doubles ; gourmande)[+-]?d+(.d+)?(%|[A-z]+)?
(entier et décimal, pourcentage optionnel ou avec unité)#[0-9A-f]{3,6}
(couleur)[A-z0-9_-]+
(Mots clés, dénomination des couleurs, "facilité d'entrée", etc.)([w-]+)([^)]+)
(类似url()
、calc()
fonction > etc.)Premier filtre
J'imagine que vous pourriez effectuer un filtrage avant d'essayer d'identifier ces modèles. Peut-être que nous coupons d'abord la chaîne de valeur. Comme vous l'avez mentionné,
和
>
可以在preprocessPairs()
est échappé au début de la fonction car il n'apparaîtra comme aucun des modèles que nous avons ci-dessus. Si vous ne souhaitez pas que les points-virgules non échappés apparaissent n'importe où, vous pouvez également les échapper.Modèle de reconnaissance
Nous pouvons ensuite essayer d'identifier ces modèles dans values, et pour chaque modèle, nous devrons peut-être réexécuter le filtrage. Nous nous attendons à ce que ces modèles soient séparés par quelques (ou deux) caractères d'espacement.
Cela devrait être bien d'inclure la prise en charge des chaînes multilignes, qui sont une nouvelle ligne échappée.
Local
Nous devons réaliser que nous avons au moins deux contextes à filtrer : HTML et CSS. Quand on est dans l'attribut
元素中包含样式时,输入必须是安全的,同时它必须是有效的 CSS。幸运的是,您没有将 CSS 包含在元素的
style
, c'est donc un peu plus facile.Filtrage basé sur un modèle de valeur
Les points 1 à 5 seront donc très simples et la plupart des valeurs seront couvertes par un simple filtrage et découpage depuis l'avant. Avec quelques ajouts (je ne sais pas quel impact sur les performances), il pourrait même effectuer des vérifications supplémentaires pour les unités, mots-clés, etc.
Mais par rapport à d’autres points, je pense que le défi relativement plus important est le point 6. Vous pourriez décider de simplement désactiver
url()
,让您检查函数的输入,因此例如您可能想要转义分号,甚至可能通过微小的调整再次检查函数内的模式例如对于calc()
dans ce style personnalisé.Conclusion
Dans l’ensemble, c’est mon avis. Avec quelques ajustements à ces expressions régulières, cela devrait compléter ce que vous faites déjà et vous donner autant de flexibilité que possible lors de la saisie de CSS, tout en vous évitant d'avoir à modifier votre code à chaque fois que vous modifiez une fonctionnalité CSS.
Exemple
Commentez, discutez, critiquez et faites-moi savoir si j'ai oublié d'aborder un sujet qui vous intéresse particulièrement.
Source
Avertissement : je ne suis pas l'auteur, le propriétaire, l'investisseur ou le contributeur des sources mentionnées ci-dessous. Il se trouve que je les utilise pour obtenir des informations.