recherche

Maison  >  Questions et réponses  >  le corps du texte

Attribuez en toute sécurité des entrées non fiables aux propriétés personnalisées CSS sans JavaScript : un guide

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 :

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.

P粉356361722P粉356361722445 Il y a quelques jours722

répondre à tous(1)je répondrai

  • P粉898107874

    P粉8981078742023-09-07 21:34:20

    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é) :

    1. '.*' (chaîne entourée d'apostrophes ; gourmand)
    2. ".*" (Chaîne entre guillemets doubles ; gourmande)
    3. [+-]?d+(.d+)?(%|[A-z]+)? (entier et décimal, pourcentage optionnel ou avec unité)
    4. #[0-9A-f]{3,6}(couleur)
    5. [A-z0-9_-]+ (Mots clés, dénomination des couleurs, "facilité d'entrée", etc.)
    6. ([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