ENbext.dev
DocumentationInclusions côté serveur

Traduction automatique depuis l’anglais. Consulter l’original.

Sur cette page

Les inclusions authentifiées

La plupart des pages contiennent des fragments qui n'ont de sens que pour certains utilisateurs : barres d'outils d'administration, teasers de contenu premium, CTA de connexion, listes déroulantes de profil utilisateur. Le contrôle côté client fait fuir le balisage vers le DOM et provoque un changement de disposition. Les inclusions authentifiées résolvent le bon contenu côté serveur, de sorte que la réponse ne contient jamais de fragments que l'utilisateur ne devrait pas voir.

html
<bext-include src="/partials/admin-toolbar"
  auth="required" role="admin"
  vary="role" ttl="30m"
>
  <!-- optional fallback for non-admins -->
</bext-include>

Les administrateurs authentifiés voient la barre d'outils ; tout le monde voit la solution de repli (ou rien).

Attributs#

Attribut Valeurs But
auth required Résoudre uniquement pour les utilisateurs authentifiés
auth anonymous Résoudre uniquement pour les utilisateurs non authentifiés
role CSV des noms de rôles Résoudre uniquement si l'utilisateur a l'un de ces rôles

Utilisez auth="required" seul pour tout utilisateur connecté. Ajoutez role="admin" pour exiger un rôle spécifique. Répertoriez plusieurs rôles avec des virgules pour « n’importe quelle correspondance ».

Conseil

La porte d'authentification exécute avant le résolveur et avant toute recherche de cache. Pour les utilisateurs anonymes qui accèdent à une inclusion auth="required", l'inclusion est rejetée sans frais : aucun résolveur n'est invoqué et aucune clé de cache n'est calculée.

Contexte de la séance#

Portes d'authentification lues à partir du SessionInfo de la requête :

rust
pub struct SessionInfo {
    pub authenticated: bool,
    pub user_id: Option<String>,
    pub email: Option<String>,
    pub roles: Vec<String>,
    pub is_super_admin: bool,
}

Ceci est renseigné une fois par demande par le middleware d'authentification de bext - soit à partir d'une session locale (soutenue par SQLite) soit d'un cookie de session scellé WorkOS. Le système d'inclusion ne se soucie pas de quoi - il lit le SessionInfo et prend des décisions.

Modèles courants#

Liste déroulante Connexion/Utilisateur#

html
<!-- Anonymous: show sign-in button -->
<bext-include src="/partials/signin-button"
  auth="anonymous"
  vary="auth"
></bext-include>

<!-- Authenticated: show user dropdown -->
<bext-include src="/partials/user-dropdown"
  auth="required"
  vary="auth"
></bext-include>

Les deux peuvent mettre en cache en toute sécurité car ils déclarent vary="auth" — chaque entrée de cache est spécifique à l'état d'authentification.

Contenu spécifique au rôle#

html
<bext-include src="/partials/admin-nav"
  auth="required" role="admin,superadmin"
  vary="role"
></bext-include>

Tout rôle de la liste CSV compte. Les super administrateurs contournent automatiquement les vérifications de rôle (ils ont accès à tout).

Teasers de contenu premium#

html
<bext-include src="/partials/premium-content"
  auth="required" role="paid"
>
  <div class="upgrade-prompt">
    <p>This is premium content — <a href="/upgrade">upgrade to see</a>.</p>
  </div>
</bext-include>

Les utilisateurs payants obtiennent le contenu. Les utilisateurs non payants voient l'invite de mise à niveau (le repli entre les balises d'ouverture et de fermeture).

Masquer les liens d'administration des utilisateurs anonymes#

html
<nav>
  <a href="/home">Home</a>
  <bext-include src="/partials/admin-link"
    auth="required" role="admin"
  >
    <!-- empty fallback — admin link simply omitted -->
  </bext-include>
</nav>

Contenu de secours#

Le contenu entre <bext-include> et </bext-include> est le repli rendu lorsque la porte d'authentification rejette :

html
<bext-include src="/partials/members-only" auth="required">
  <p>Please <a href="/login">sign in</a> to continue reading.</p>
</bext-include>
  • Utilisateur authentifié : voit le contenu members-only résolu.
  • Utilisateur anonyme : voit le message "Veuillez vous connecter".
  • Repli manquant : émet une chaîne vide (l'élément disparaît).

Fallback fonctionne également avec l'attribut stub de SSI et alt d'ESI — voir Compatibilité SSI et ESI.

Attention

Ajoutez toujours vary="role" (ou vary="auth" ) à toute inclusion authentifiée qui utilise également ttl. Sans cela, le contenu résolu du premier utilisateur est mis en cache et diffusé à tout le monde, y compris aux utilisateurs qui ne devraient pas le voir. bext enregistre un avertissement ; le mode strict désactive entièrement la mise en cache pour ces inclusions.

Garde anti-empoisonnement du cache#

Les inclusions authentifiées qui sont mises en cache doivent varier en fonction de la dimension appropriée. Sinon, le cache servirait le contenu administrateur aux non-administrateurs :

html
<!-- BAD: first admin request caches admin content; then served to anyone -->
<bext-include src="/partials/admin-toolbar"
  auth="required" role="admin"
  ttl="30m"
></bext-include>

<!-- GOOD: separate cache entry per role -->
<bext-include src="/partials/admin-toolbar"
  auth="required" role="admin"
  ttl="30m" vary="role"
></bext-include>

bext enregistre un avertissement lorsqu'une inclusion authentifiée est mise en cache sans vary="role" ou vary="auth". En mode strict (configurable), la mise en cache est désactivée pour ces inclusions au lieu de diffuser un contenu potentiellement incorrect.

code
WARN auth-gated include /partials/admin-toolbar is cacheable but doesn't
     vary on role — cache poisoning risk

Super administrateurs#

Les utilisateurs avec is_super_admin=true contournent toutes les vérifications de rôle :

html
<bext-include src="/partials/staff-tools"
  auth="required" role="editor,moderator"
></bext-include>

Un super administrateur voit cela inclure même sans le rôle editor ou moderator. Le statut de super administrateur est défini par la variable d'environnement SUPER_ADMIN_EMAILS (e-mails séparés par des virgules) et prend effet via SessionInfo::has_any_role.

Performance#

La porte d'authentification exécute avant la résolution et avant les recherches dans le cache. Pour les utilisateurs anonymes qui frappent un auth="required", citons :

code
Request → parse directive → auth gate REJECTS → return fallback

Coût de résolution nul. Calcul de clé de cache zéro. Zéro appel de résolveur. Le chemin le moins cher possible pour le cas courant où « la plupart des utilisateurs ne voient pas cela ».

Intégration avec des résolveurs personnalisés#

Les résolveurs de plugin reçoivent la session via le contexte d'inclusion :

rust
impl IncludeResolver for MyCustomResolver {
    fn resolve(&self, d: &IncludeDirective, ctx: &IncludeContext) -> Option<String> {
        // Auth gate has already approved — we know the user qualifies.
        let user = ctx.session.as_ref()?;
        Some(render_personalized(&user.email))
    }
}

Les résolveurs personnalisés n'ont pas besoin de revérifier l'authentification ; le AuthGateResolver a déjà filtré les requêtes avant que la chaîne ne les atteigne.

Voir aussi#

Modifier cette page ↗Besoin d’aide ? ↗
Rechercher dans la documentation

Saisissez un sujet, une commande ou une question.