Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,075 of 9,075 pages
About the help in other languages
All help pages

Anfrageregeln: content/view/full und jede andere Modul-View absichern

Exponential 6.0.15. Einstellungen in settings/requestrules.ini. Code in kernel/private/classes/requestrules/. Befehl bin/php/ezrequestrules.php. Tests in tests/tests/kernel/classes/requestrules/.

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/bc/6.0/view_full_security.md

On this page

This page is a translation. Read the English original

Anfrageregeln: content/view/full und jede andere Modul-View absichern

Exponential 6.0.15. Einstellungen in settings/requestrules.ini. Code in kernel/private/classes/requestrules/. Befehl bin/php/ezrequestrules.php. Tests in tests/tests/kernel/classes/requestrules/.

Die Anfrageregeln entscheiden, was mit einer Anfrage geschieht, unmittelbar bevor ihre Modul-View läuft. Eine Regel sagt, wann (Bedingungen wie „als System-URL eingegeben“, „Vollansicht“, „dem Benutzer fehlt eine Richtlinie“, „unter Knoten 864“, „aus diesem Netzwerk“) und was (Weiterleitung auf den URL-Alias, nicht gefunden, Zugriff verweigert, zuerst anmelden, Weiterleitung, Umschreiben, Protokollieren). Regeln werden in INI geschrieben, lassen sich pro Siteaccess einschalten, können von jeder Erweiterung in PHP erweitert werden und sind an Rollenrichtlinien gebunden, sodass im Rolleneditor entschieden wird, wer ausgenommen ist, nicht in einer Datei.

Sie entstanden für eine Frage, die Einstellungen bisher nicht beantworten konnten:

Wie halte ich anonyme Besucher davon ab, Seiten über ihre System-URL /content/view/full/123 zu öffnen, während dieselbe Seite unter ihrem URL-Alias /Fit-Healthy/Some-Article für alle weiter funktioniert?

Die Antwort ist eine Regel, einsatzbereit ausgeliefert und mit zwei Zeilen eingeschaltet.

Lesen Sie diese Seite, wenn Sie Besucher von System-URLs fernhalten, eine Sektion schützen oder vor einer Modul-View eine beliebige Prüfung ausführen möchten; und vor dem Upgrade, wenn Sie sich auf [SiteAccessRules] oder auf PolicyOmitList[] verlassen.

Kurz gesagt

Was sich geändert hatNeue Engine für Anfrageregeln (settings/requestrules.ini, kernel/private/classes/requestrules/), die vor jeder Modul-View gefragt wird. Neue Richtlinienfunktion content/view_system_url. Neuer Befehl bin/php/ezrequestrules.php (auflisten, prüfen, erklären). Drei Regeln werden definiert und ausgeschaltet ausgeliefert.
Wer betroffen istNiemand, solange keine Regel in RuleList[] aufgeführt ist. Dann: Jede Modul-View wird gefragt, auch Views aus PolicyOmitList[]. [SiteAccessRules] funktioniert weiter und wird zuerst geprüft. Rollen mit content/* schließen die neue Richtlinienfunktion ein.
Wie Sie es prüfenphp bin/php/ezrequestrules.php -s <siteaccess> --check
Wie Sie es behebenNichts zu beheben. Um sie zu verwenden, folgen Sie dem Schnellstart; entfernen Sie jede Weiterleitung, die Sie zum selben Zweck in full.tpl eingebaut haben.

Inhalt

  1. Schnellstart
  2. Warum Einstellungen und Richtlinien allein es nicht konnten
  3. Wie über eine Anfrage entschieden wird
  4. Regeln schreiben
  5. Referenz: Bedingungen
  6. Referenz: Aktionen
  7. Referenz: Fakten
  8. Die Richtlinienfunktion content/view_system_url
  9. Rezepte
  10. Die Regeln in PHP erweitern
  11. Die Engine aus PHP verwenden
  12. Prüfen, erklären und testen
  13. Caches
  14. Exponential Velocity und persistente Worker
  15. Leistung
  16. Hinweise zur Sicherheit
  17. Was die Regeln nicht sehen
  18. Kompatibilität und Upgrade
  19. Fehlerbehebung
  20. Dateien

1. Schnellstart

Ziel: Anonyme Besucher (und alle anderen ohne eine bestimmte Richtlinie), die /content/view/full/<node> eingeben, werden mit einem 301 auf den URL-Alias des Knotens geschickt. Ein Knoten ohne eigenen Alias antwortet mit 404. Administratoren und alle, denen Sie die Richtlinie geben, verwenden weiterhin System-URLs.

Schritt 1. Schalten Sie die ausgelieferte Regel für jeden öffentlichen Siteaccess ein, in settings/siteaccess/<siteaccess>/requestrules.ini.append.php:

<?php /* #?ini charset="utf-8"?

[RequestRuleSettings]
RuleList[]
RuleList[]=system_url_full_view_to_alias

*/ ?>

Lassen Sie die Siteaccesses für Administration und Editor unverändert: Redakteure verwenden dort absichtlich System-URLs.

Schritt 2. Geben Sie die Richtlinie content / view_system_url den Rollen, die auf den öffentlichen Siteaccesses System-URLs behalten sollen, etwa einer Rolle Editor (siehe Abschnitt 8). Administratoren haben sie bereits über content/* oder */*.

Schritt 3. Stellen Sie bereit und prüfen Sie:

./console exp:velocity deploy --no-autoload --allow-root-user   # clears the INI and page caches, restarts Velocity
php bin/php/ezrequestrules.php -s site --check --allow-root-user
php bin/php/ezrequestrules.php -s site --uri=content/view/full/2 --allow-root-user
curl -sk -o /dev/null -w '%{http_code} %{redirect_url}\n' https://www.example.com/content/view/full/2

Ohne Velocity müssen die INI- und Seiten-Caches trotzdem geleert werden: php bin/php/ezcache.php --clear-tag=ini --allow-root-user, dann --clear-id=content,exphttpcache.

So sieht es auf einer Referenzinstallation aus (2026-10-02), unter Apache und Velocity gleichermaßen:

AnfrageAnonymAdministrator
/content/view/full/2301 auf /websites, Cache-Control: private, no-store200
/content/view/full/2/(offset)/10?x=1301 auf /websites/(offset)/10?x=1200
/fit-healthy (der Alias)200, wie bisher gecacht200
/ (Startseite, IndexPage=/content/view/full/89)200200
/content/view/line/2 (ein anderer View-Modus)200200
/content/view/full/999999 (kein solcher Knoten)404404

Mehr brauchen die meisten Websites nicht. Der Rest dieser Anleitung erklärt den Mechanismus vollständig: was sich wie entscheiden lässt, wie man ihn erweitert und wie man erkennt, was er tut.

2. Warum Einstellungen und Richtlinien allein es nicht konnten

Bevor es die Anfrageregeln gab, gab es vier Werkzeuge, und keines konnte „diese View, auf diesem Weg erreicht, für diese Benutzer“ ausdrücken:

WerkzeugWas es tutWarum es nicht die Antwort ist
Rollenrichtlinie content/read, eingeschränkt nach Klasse, Sektion, Besitzer, Gruppe, Knoten, Teilbaum, StatusEntscheidet, welche Inhalte ein Benutzer lesen darfNicht, welchen View-Modus oder welche URL. Nehmen Sie content/read weg, verschwinden die Inhalte überall: unter ihrem Alias, in Listen, in Fetches auf anderen Seiten.
site.ini [SiteAccessRules] Rules[] (access;disable, module;content/view)Schaltet ein Modul oder ein Modul/eine View für einen Siteaccess ausEs gilt für jeden Benutzer. Es wird nach der Übersetzung des URL-Alias geprüft, daher nimmt das Ausschalten von content/view jeden Alias mit: Die ganze Website antwortet mit 404. Und es kann full nicht von line unterscheiden.
site.ini [SiteAccessSettings] RequireUserLogin + AnonymousAccessList[]Anmeldung für einen ganzen Siteaccess, mit AusnahmenAlles oder nichts pro Siteaccess.
Eine Weiterleitung in einem Template full.tplFunktioniert in einem DesignDie Vollansicht ist bereits gebaut und vielleicht gecacht, wenn das Template läuft. Sie gehört zu einem Design, nicht zum System.

Die entscheidende Tatsache ist, dass ein URL-Alias content/view/full/<node> ist: Der Kernel übersetzt /Fit-Healthy in content/view/full/89, bevor irgendetwas den Zugriff prüft. Der Kernel wusste, was der Besucher eingegeben hatte (er hält die Adresse vor der Übersetzung fest), aber nichts nutzte das. Die Anfrageregeln nutzen es: Der Fakt requested_via ist system, alias, wildcard oder index.

3. Wie über eine Anfrage entschieden wird

 request
   |
   |-- served from a page cache?  (role-aware HTTP cache early exit, Velocity response cache)
   |       yes -> the stored page. Rule-dependent pages are never stored: section 13
   |
   v  the kernel (ezpKernelWeb::dispatchLoop)
   1. address typed kept                 typed_uri, e.g. "Fit-Healthy" or "content/view/full/123"
   2. URL alias / wildcard translation   "Fit-Healthy" -> "content/view/full/89"; requested_via = alias
      a moved alias                      -> 301 to its new address (no rule is asked)
   3. [SiteAccessRules]                  module or view switched off -> not found
   4. the module and view exist?         no -> not found
   5. role policies                      not allowed -> access denied / sign in
   6. REQUEST RULES                      the first rule whose conditions all match decides
   7. the module view runs               (unless step 6 decided otherwise)

Was aus dieser Reihenfolge folgt:

  • Regeln nehmen immer nur Zugriff weg oder schicken den Besucher woandershin. Sie werden gefragt, nachdem die Richtlinien die View erlaubt haben, daher kann keine Regel eine View öffnen, die eine Richtlinie geschlossen hat. Selbst Action=allow bedeutet nur „keine weiteren Regeln fragen“.
  • Regeln sehen die übersetzte Anfrage. Eine Regel zu content/view gilt auch für Aliase. Verwenden Sie requested_via, um sie zu unterscheiden.
  • Die erste Regel, die entscheidet, entscheidet. Die Reihenfolge zählt. Stellen Sie Ausnahmen (allow) vor die weiter gefassten Regeln, zu denen sie Ausnahmen sind.
  • Eine Regel, die passt, aber nicht handeln kann, gibt weiter. redirect_to_alias kann bei einem Knoten ohne Alias nicht handeln: Die FallbackAction der Regel läuft, und ohne eine solche wird die nächste Regel gefragt.
  • Keine Regel hat gepasst? Die Anfrage läuft wie immer. Eine leere RuleList kostet etwa 2,6 µs pro Anfrage (Abschnitt 15).
  • Jede Antwort einer Regel außer allow wird mit Cache-Control: private, no-store gesendet. Sie hängt davon ab, wer gefragt hat, daher darf kein Browser und kein gemeinsamer Cache sie behalten. Ein Browser, der ein 301 behielte, würde einen Besucher auch nach seiner Anmeldung weiter umleiten.

4. Regeln schreiben

4.1 Wohin die Einstellungen gehören

Bearbeiten Sie nie settings/requestrules.ini. Überschreiben Sie sie wie jede INI-Datei:

DateiGeltungsbereich
settings/override/requestrules.ini.append.phpjeder Siteaccess
settings/siteaccess/<name>/requestrules.ini.append.phpein Siteaccess (überschreibt das Obige)
extension/<ext>/settings/requestrules.ini.append.phpaus einer aktiven Erweiterung (die Regeln, Handler und Provider der Erweiterung)

RuleList[] allein auf einer Zeile leert die Liste vor den folgenden Einträgen, sodass ein Siteaccess die geerbte Liste ersetzen kann. Lassen Sie diese Zeile weg, um zu ergänzen.

4.2 Aufbau einer Regel

[RequestRuleSettings]
RuleList[]=members_area                    # switched on: asked, in this order

[Rule-members_area]                        # the rule: [Rule-<name>]
Description=Anonymous visitors of the members area sign in first.
Conditions[subtree]=864                    # ALL conditions must match
Conditions[user]=anonymous
Action=login                               # what happens then
ActionArgs[...]=...                        # arguments of the action, if it has any
FallbackAction=notfound                    # optional: when the action cannot act
FallbackArgs[...]=...

Eine Regelgruppe, die existiert, aber nicht in RuleList[] steht (oder von einem Regel-Provider geliefert wird), ist ausgeschaltet. Die ausgelieferten Regeln sind so geschrieben: definiert und ausgeschaltet, bis ein Siteaccess sie aufführt.

4.3 Werte von Bedingungen

FormBedeutungBeispiel
valuepasst auf diesen WertConditions[view_mode]=full
a,b,cpasst auf einen beliebigen davon (Leerzeichen um Kommas werden ignoriert)Conditions[siteaccess]=site, bold
!a,bpasst auf keinen davon: die ganze Bedingung umgekehrtConditions[policy]=!content/view_system_url
pat*ein Shell-Muster, wo die Bedingung Muster annimmt (*, ?, [a-z])Conditions[uri]=content/view/*
name:argument im Schlüsseleine Bedingung, die einen Namen brauchtConditions[param:NodeID]=2, Conditions[header:X-Requested-With]=XMLHttpRequest

Der Abgleich unterscheidet nicht zwischen Groß- und Kleinschreibung. Eine Bedingung mit leerem Wert (oder nur !) passt nie, und --check meldet sie.

4.4 Mehrere Regeln

RuleList[]
RuleList[]=robots_may_see_node_2      # 1. exception first
RuleList[]=system_url_full_view_to_alias   # 2. the general rule

[Rule-robots_may_see_node_2]
Conditions[node]=2
Conditions[requested_via]=system
Action=allow

Die Regeln werden in der Reihenfolge von RuleList[] gefragt, gefolgt von den Regeln aus RuleProviders[], in deren Reihenfolge.

4.5 Alles ausschalten

[RequestRuleSettings]
Enabled=false

Keine Regel wird gefragt, und der Kernel verhält sich genau so wie vor dieser Funktion.

5. Referenz: Bedingungen

Stabil bedeutet, dass die Antwort für jede Anfrage gleich ist, die eine gespeicherte Seite beantwortet: Die Cache-Schlüssel enthalten, was die Bedingung liest. Eine Regel mit einer nicht stabilen Bedingung hält die Seiten, über die sie entscheiden könnte, aus den gemeinsamen Caches heraus (Abschnitt 13). Bevorzugen Sie stabile Bedingungen, wo Sie können.

BedingungLiest (Fakt)WerteMusterStabilBeispiel
requested_viarequested_viasystem (als Modul/View eingegeben), alias (ein URL-Alias), wildcard (ein URL-Wildcard), index (die Startseite, IndexPage)neinjaConditions[requested_via]=system
urityped_uri: die eingegebene Adresse, ohne Siteaccess, Schrägstriche oder QueryAdressenjajaConditions[uri]=content/view/*
resolved_uriresolved_uri: die Systemadresse, die ausgeführt wirdAdressenjajaConditions[resolved_uri]=content/view/full/89
modulemoduleModulnamenneinjaConditions[module]=content,shop
module_viewmodule/viewModul/ViewjajaConditions[module_view]=content/*
view_modeview_mode: der ViewMode von content/viewView-ModineinjaConditions[view_mode]=full
param:<Name>params[<Name>]: ein View-Parameter, über seinen Namen in der module.php des ModulsWertejajaConditions[param:NodeID]=2,43
nodenode_id: der Knoten von content/viewKnoten-IDsneinjaConditions[node]=2
subtreepath_ids: der Knoten und seine VorfahrenKnoten-IDsneinjaConditions[subtree]=864
classclass_identifier des KnotensKlassenbezeichnerneinjaConditions[class]=article,blog_post
sectionsection_id, section_identifier des ObjektsIDs oder BezeichnerneinjaConditions[section]=members
statestate_identifiers: group/state des ObjektsBezeichnerjajaConditions[state]=ez_lock/locked
useris_anonymousanonymous, logged_inneinjaConditions[user]=anonymous
rolerole_names: dem Benutzer oder seinen Gruppen zugewiesene RollenRollennamenneinjaConditions[role]=Partner
policyhas_access: eZUser::hasAccessTo(); eingeschränkter Zugriff zähltModul/FunktionneinjaConditions[policy]=!content/view_system_url
siteaccesssiteaccessNamen von SiteaccessesjajaConditions[siteaccess]=site,bold*
methodmethodGET, POST, HEAD, ...neinjaConditions[method]=!POST
schemeschemehttp, httpsneinjaConditions[scheme]=http
hosthost: der Hostname, ohne PortHostnamenjajaConditions[host]=staging.*
user_iduser_id: die Objekt-ID des BenutzersIDsneinneinConditions[user_id]=14
user_loginuser_loginAnmeldenamenjaneinConditions[user_login]=svc-*
groupgroup_ids: Objekt-IDs der Benutzergruppen des BenutzersIDsneinneinConditions[group]=12
header:<Name>ein Anfrage-Header; * = überhaupt gesendetWertejaneinConditions[header:X-Requested-With]=XMLHttpRequest
ipclient_ipAdressen und CIDR-Netze, IPv4 und IPv6neinneinConditions[ip]=10.0.0.0/8, 2001:db8::/32
fact:<name>jeder Fakt, auch einer einer ErweiterungWertejaneinConditions[fact:customer_tier]=gold

user_id, user_login und group sind nicht stabil, weil der rollenabhängige HTTP-Cache eine gespeicherte Seite zwischen allen Benutzern mit denselben Rollen teilt.

Bedingungen zum Knoten (node, subtree, class, section, state) passen nie auf eine Anfrage, die keinen Knoten betrifft. Ihre Fakten sind dann null, und eine verneinte Bedingung (!article) passt ebenfalls nicht.

6. Referenz: Aktionen

AktionAntwortArgumenteKann nicht handeln (fällt zurück), wenn
allowdie View läuft; keine spätere Regel wird gefragtkeinenie
notfounddie Seite „nicht gefunden“, HTTP 404 (Kernel-Fehler 3). Verrät nicht, ob die Seite existiertkeinenie
forbiddendie Seite „Zugriff verweigert“, HTTP 403 (Kernel-Fehler 1), wie bei einer fehlenden Richtliniekeinenie
loginanonym: 302 auf user/login und nach der Anmeldung zurück zur Seite. Angemeldet: „Zugriff verweigert“keinedie Anfrage ist selbst eine Anmelde-View (user/login, logout, register, activate, success, forgotpassword, password), sodass keine Regel eine Schleife erzeugen kann
redirectHTTP-Weiterleitungto (erforderlich; Platzhalter), status 301, 302 (Standard), 303, 307, 308to ist leer
redirect_to_aliasHTTP-Weiterleitung auf den URL-Alias des Knotens, mit den Benutzerparametern der View (/(offset)/10); der Kernel behält den Query-Stringstatus (Standard 301)betrifft keinen Knoten, oder der Knoten hat keinen eigenen Alias
rewriteder Kernel führt stattdessen eine andere Adresse aus, ohne Weiterleitung; der Besucher behält die eingegebene Adresse. Die Regeln werden für die neue Adresse erneut gefragt, höchstens MaxRewrites (3) Mal, danach „nicht gefunden“to (erforderlich; Platzhalter)to ist leer
logschreibt eine Zeile nach var/log/requestrules.log; gibt immer weiter (an den Fallback oder die nächste Regel)message (Platzhalter; Standard: die Adresse)immer: dafür ist sie da

Ein Weiterleitungsziel kann ein Pfad innerhalb des Siteaccess sein (/about-us), eine Systemadresse (/content/view/full/2, als Alias dieses Knotens gesendet, wie jede Weiterleitung des Kernels) oder eine absolute URL. Eine absolute URL auf einem anderen Host muss in site.ini [SiteSettings] AllowedRedirectHosts[] aufgeführt sein; sonst lehnt der Kernel sie mit 403 ab.

Platzhalter

to und message können Fakten verwenden: {node_id}, {typed_uri}, {view_mode}, {siteaccess}, {user_login}, jeden skalaren Fakt {name}, einen View-Parameter {param:NodeID}, einen Header {header:Host}. Ein unbekannter Platzhalter oder einer, dessen Fakt kein einzelner Wert ist, wird leer.

log mit einem Fallback: erst protokollieren, dann handeln

Action=log
ActionArgs[message]=refused {typed_uri} for {user_login}
FallbackAction=notfound

Das schreibt die Zeile und antwortet dann mit „nicht gefunden“: Eine Regel protokolliert und lehnt zugleich ab.

7. Referenz: Fakten

Fakten sind das, was Bedingungen und Aktionen lesen. Der Kernel definiert sie für jede Anfrage (ezpRequestRuleKernel::context()). Die meisten werden erst aufgelöst, wenn eine Regel sie liest: Eine Regel zur Adresse lädt nie den Knoten, und der Knoten wird höchstens einmal geladen, egal wie viele Regeln fragen.

FaktTypBeispielKosten
typed_uristringcontent/view/full/2, fit-healthy, `` (Startseite)frei
requested_viastringsystem, alias, wildcard, indexfrei
resolved_uristringcontent/view/full/89frei
module, viewstringcontent, viewfrei
paramsarray{"ViewMode":"full","NodeID":"89"}frei
view_modestring|nullfullfrei
node_idint|null89frei
user_parametersarray{"offset":"10"}frei
user_parameters_uristring/(offset)/10frei
rewritesintbisherige Umschreibungen in dieser Anfragefrei
siteaccess, methodstringsite, GETfrei
scheme, host, client_ip, headersstring / arrayhttps, www.example.com, 10.1.2.3, Namen in Kleinbuchstabenbei Verwendung
usereZUserder aktuelle Benutzerfrei
user_idint10 (anonym)frei
is_anonymous, user_login, group_ids, role_namesbei Verwendung
has_accesscallable( module, function ) : boolbei Verwendung
node, objecteZContentObjectTreeNode / eZContentObjectbei Verwendung, ein Fetch
url_alias, path_ids, class_identifieraus dem Knotenfit-healthy, [1,2,89], frontpagebei Verwendung
section_id, section_identifier, state_identifiersaus dem Objekt1, standard, ["ez_lock/not_locked"]bei Verwendung
rules_vary_by_requestboolvon der Engine gesetzt (Abschnitt 13)

Eine Erweiterung fügt Fakten mit einem Fakt-Provider hinzu (10.3). Ein Resolver, der eine Ausnahme wirft, wird in die Debug-Ausgabe geschrieben und ergibt null, sodass ein defekter Fakt nie eine Seite zerstört.

8. Die Richtlinienfunktion content/view_system_url

Eine neue Funktion des Moduls content. Sie hat keine Einschränkungen und wird von keiner View geprüft. Es gibt sie, damit die Frage, wer von einer Regel für System-URLs ausgenommen ist, eine Entscheidung über Rollen ist:

Conditions[policy]=!content/view_system_url     # the rule applies to users WITHOUT it
  • Administratoren haben sie über content/* (alle Funktionen des Moduls content) oder */*.
  • Anonym hat sie nicht, sofern Sie sie nicht hinzufügen; lassen Sie sie also weg.
  • Redakteure, die auf dem öffentlichen Siteaccess mit System-URLs arbeiten, brauchen sie: Öffnen Sie in der Administration Rollen und Richtlinien, dann die Rolle (z. B. Editor), Neue Richtlinie, Modul content, Funktion view_system_url, Vollen Zugriff gewähren.

Dasselbe Muster funktioniert mit jeder Richtlinie, auch mit den Funktionen Ihres eigenen Moduls: Conditions[policy]=!mymodule/premium.

9. Rezepte

Jedes Rezept ist vollständig: Setzen Sie die Gruppe in requestrules.ini.append.php und fügen Sie den Namen zu RuleList[] hinzu. Knoten-IDs, Klassenbezeichner und Adressen sind Beispiele. Prüfen Sie Ihre mit bin/php/ezrequestrules.php.

9.1 System-URLs auf den Alias (ausgeliefert: system_url_full_view_to_alias)

[Rule-system_url_full_view_to_alias]
Conditions[requested_via]=system
Conditions[module_view]=content/view
Conditions[view_mode]=full
Conditions[policy]=!content/view_system_url
Action=redirect_to_alias
ActionArgs[status]=301
FallbackAction=notfound

9.2 Streng: keine System-URL in irgendeinem View-Modus (ausgeliefert: system_url_content_view_notfound)

[Rule-system_url_content_view_notfound]
Conditions[requested_via]=system
Conditions[module_view]=content/view
Conditions[policy]=!content/view_system_url
Action=notfound

Achten Sie auf die Views, die Ihr Design über eine URL abruft (zum Beispiel ein AJAX-Aufruf von content/view/line/<node>). Nehmen Sie sie zuerst aus (9.11), oder bleiben Sie bei 9.1.

9.3 Erst protokollieren, dann durchsetzen (ausgeliefert: system_url_full_view_audit)

Setzen Sie die Protokollregel vor die Regel, die sie vorab zeigt. Sie protokolliert und gibt weiter:

RuleList[]
RuleList[]=system_url_full_view_audit
$ tail var/log/requestrules.log
[ Oct 02 2026 06:01:12 ] [] [system_url_full_view_audit] GET system URL content/view/full/2 (node 2) by anonymous ip=10.1.2.3

Wenn das Log nur zeigt, was Sie erwarten, fügen Sie die durchsetzende Regel dahinter hinzu oder ersetzen Sie die Protokollregel durch sie.

9.4 Ein Mitgliederbereich: zuerst anmelden

[Rule-members_area]
Description=Below node 864, anonymous visitors sign in first and come back.
Conditions[subtree]=864
Conditions[user]=anonymous
Action=login

Was Mitglieder lesen dürfen, entscheiden weiterhin die Richtlinien; diese Regel schickt anonyme Besucher nur auf die Anmeldeseite statt auf ein bloßes „Zugriff verweigert“.

9.5 Eine Intranet-Sektion, nur aus den Büronetzen

[Rule-intranet_from_office_only]
Conditions[section]=intranet
Conditions[ip]=!10.0.0.0/8, 192.168.0.0/16, 2001:db8:42::/48
Action=notfound

Hinter einem Load Balancer setzen Sie site.ini [HTTPHeaderSettings] ClientIpByCustomHTTPHeader=X-Forwarded-For, damit client_ip der Besucher ist und nicht der Load Balancer. Da ip sich pro Anfrage unterscheidet, werden Intranet-Seiten nicht in den gemeinsamen Caches gespeichert.

9.6 Eine Klasse nie anonymen Besuchern zeigen

[Rule-internal_memos_hidden]
Conditions[class]=internal_memo
Conditions[user]=anonymous
Action=notfound

9.7 Einen ganzen Zweig verschieben: alte Adressen auf neue

[Rule-old_news_to_archive]
Conditions[subtree]=1200
Conditions[requested_via]=alias
Action=redirect
ActionArgs[to]=/archive/node/{node_id}
ActionArgs[status]=308

Für Adressen, die sich auf keinen Knoten mehr auflösen, verwenden Sie URL-Wildcards (content/urlwildcards). Regeln sehen nur Adressen, die eine Modul-View erreichen (Abschnitt 17).

9.8 Wartung: Alle außer den Administratoren sehen die Wartungsseite

RuleList[]
RuleList[]=maintenance_admins_through
RuleList[]=maintenance_page

[Rule-maintenance_admins_through]
Conditions[role]=Administrator
Conditions[module]=content,user,ezjscore
Action=allow

[Rule-maintenance_page]
Conditions[module]=content
Conditions[node]=!555
Action=rewrite
ActionArgs[to]=content/view/full/555

Knoten 555 ist die Wartungsseite. user/login funktioniert weiter, sodass Administratoren sich weiterhin anmelden können.

9.9 Ein View-Modus nur für Skripte (AJAX)

[Rule-ajax_view_only_by_xhr]
Conditions[view_mode]=ajax
Conditions[header:X-Requested-With]=!XMLHttpRequest
Action=notfound

Ein Header ist nie eine Authentifizierung. Das hält Gelegenheitsbesucher und Crawler von einer Fragment-View fern; es schützt keine Daten.

9.10 Eine View, die gepostet, nie geöffnet werden muss

[Rule-action_only_by_post]
Conditions[module_view]=content/action
Conditions[method]=!POST
Action=notfound

9.11 Eine Ausnahme vor einer weiter gefassten Regel

RuleList[]
RuleList[]=line_view_for_the_menu_script
RuleList[]=system_url_content_view_notfound

[Rule-line_view_for_the_menu_script]
Conditions[module_view]=content/view
Conditions[view_mode]=line
Conditions[header:X-Requested-With]=XMLHttpRequest
Action=allow

9.12 Ein Staging-Host hinter einer Anmeldung

[Rule-staging_requires_login]
Conditions[host]=staging.*
Conditions[user]=anonymous
Conditions[module]=!user
Action=login

9.13 Partnerseiten für Partner, ein Teaser für alle anderen

[Rule-partner_pages]
Conditions[subtree]=900
Conditions[role]=!Partner,Administrator
Action=redirect
ActionArgs[to]=/become-a-partner
ActionArgs[status]=302

9.14 Eine Seite stilllegen, aber ihre Adresse behalten

[Rule-retired_offer_shows_successor]
Conditions[node]=123
Action=rewrite
ActionArgs[to]=content/view/full/456

Der Besucher bleibt auf der alten Adresse und sieht Knoten 456.

9.15 Unterschiedliche Regeln pro Siteaccess

settings/siteaccess/site/requestrules.ini.append.php:

[RequestRuleSettings]
RuleList[]
RuleList[]=system_url_full_view_to_alias

settings/siteaccess/bold_ger/requestrules.ini.append.php:

[RequestRuleSettings]
RuleList[]
RuleList[]=system_url_content_view_notfound

Dieselben Regeln können auch in einer Datei mit Conditions[siteaccess]=... stehen.

9.16 HTTPS nur für angemeldete Benutzer

[Rule-signed_in_over_https]
Conditions[scheme]=http
Conditions[user]=logged_in
Action=redirect
ActionArgs[to]=https://{host}/{typed_uri}
ActionArgs[status]=308

(Fügen Sie den Host zu AllowedRedirectHosts[] hinzu, wenn es nicht der aktuelle ist; hier ist er es.)

10. Die Regeln in PHP erweitern

Eine Erweiterung fügt Bedingungen, Aktionen, Fakten und Regeln hinzu. Jedes davon ist eine kleine Klasse, die in der extension/<ext>/settings/requestrules.ini.append.php der Erweiterung genannt und vom Autoloader gefunden wird. Führen Sie nach dem Hinzufügen der Klassen php bin/php/ezpgenerateautoloads.php -e aus.

Die Beispiele bauen eine Erweiterung, myshop, die Premium-Artikel zahlenden Kunden vorbehält.

10.1 Eine Bedingung

<?php
// extension/myshop/classes/myshopcustomertiercondition.php
/**
 * customer_tier: the tier of the signed-in customer, from the fact
 * 'customer_tier' (myShopFactProvider): Conditions[customer_tier]=gold,silver
 */
class myShopCustomerTierCondition implements ezpRequestRuleCondition
{
    public function matches( ezpRequestContext $context, array $values, $argument )
    {
        $tier = $context->get( 'customer_tier' );     // resolved on first use
        foreach ( $values as $value )
        {
            if ( strcasecmp( $value, (string)$tier ) === 0 )
                return true;
        }
        return false;
    }
}

Regeln für eine Bedingung:

  • Lesen Sie nur Fakten. Greifen Sie in matches() nie direkt auf die Datenbank zu. Legen Sie das in einen Fakt, damit es einmal und erst bei Bedarf geladen wird und in Tests vorgegeben werden kann.
  • Ändern Sie nie etwas. Eine Bedingung kann mehrmals oder gar nicht gefragt werden.
  • $values ist nie leer, und das „!“ ist bereits behandelt. Beantworten Sie „passt irgendein Wert?“.
  • Stabil? Fügen Sie implements ezpRequestRuleCondition, ezpRequestRuleStableCondition nur hinzu, wenn die Antwort von nichts als den Cache-Schlüsseln abhängt (Adresse, Siteaccess, Host, Schema, der Knoten, die Rollen und Richtlinien des Benutzers). Eine Kundenstufe gilt pro Benutzer und ist daher nicht stabil: Lassen Sie es weg, und Seiten, über die sie entscheiden könnte, bleiben aus den gemeinsamen Caches heraus.

Eine Bedingung, die einen Fakt vergleicht, kann einfach so aussehen:

class myShopRegionCondition extends ezpRequestFactCondition { protected $fact = 'region'; protected $patterns = true; }

10.2 Eine Aktion

<?php
// extension/myshop/classes/myshoppaywallaction.php
/**
 * paywall: shows the paywall page (design:myshop/paywall.tpl) in place of the
 * article, with HTTP 402. ActionArgs[template]=design:myshop/paywall.tpl
 */
class myShopPaywallAction implements ezpRequestRuleAction
{
    public function decide( ezpRequestContext $context, array $arguments, ezpRequestRule $rule )
    {
        $node = $context->get( 'node' );
        if ( !$node instanceof eZContentObjectTreeNode )
            return null;                                   // cannot act: fallback / next rule

        $tpl = eZTemplate::factory();
        $tpl->setVariable( 'node', $node );
        header( 'HTTP/1.1 402 Payment Required' );
        return ezpRequestRuleResult::moduleResult( array(
            'content' => $tpl->fetch( isset( $arguments['template'] ) ? $arguments['template'] : 'design:myshop/paywall.tpl' ),
            'path' => array( array( 'text' => $node->attribute( 'name' ), 'url' => false ) ),
            'node_id' => $node->attribute( 'node_id' ),
        ) );
    }
}

Eine Aktion entscheidet. Sie gibt eine der Antworten von ezpRequestRuleResult zurück, und der Kernel sendet sie:

KonstruktorAntwort
ezpRequestRuleResult::allow()die View ausführen; keine weitere Regel fragen
::notFound(), ::forbidden(), ::login()wie die eingebauten Aktionen
::redirect( $location, $status )Weiterleitung; $status 301/302/303/307/308
::rewrite( $uri )stattdessen $uri ausführen
::moduleResult( array )dieses Modulergebnis ist die Seite, innerhalb des Pagelayouts
nullkann hier nicht handeln: Der Fallback läuft, oder die nächste Regel

10.3 Ein Fakt-Provider

<?php
// extension/myshop/classes/myshopfactprovider.php
class myShopFactProvider implements ezpRequestFactProvider
{
    public function defineFacts( ezpRequestContext $context )
    {
        // A resolver: runs only if a rule reads 'customer_tier', at most once
        $context->define( 'customer_tier', function ( ezpRequestContext $c )
        {
            $user = $c->get( 'user' );
            return $user && !$c->get( 'is_anonymous' ) ? myShopCustomer::tierOf( $user->id() ) : 'none';
        } );
        $context->define( 'is_premium', function ( ezpRequestContext $c )
        {
            $object = $c->get( 'object' );
            return $object ? myShopPremium::isPremium( $object->attribute( 'id' ) ) : false;
        } );
    }
}

Fakten können auch von eingebauten Bedingungen gelesen werden: Conditions[fact:is_premium]=1.

10.4 Ein Regel-Provider (Regeln aus einer Datenbank, einer anderen Datei, einer API)

<?php
// extension/myshop/classes/myshoprulesprovider.php
class myShopRulesProvider implements ezpRequestRuleProvider
{
    public function rules()
    {
        $rules = array();
        foreach ( myShopEmbargo::fetchActive() as $embargo )        // e.g. rows of a table
        {
            $rules[] = new ezpRequestRule(
                'embargo_' . $embargo->attribute( 'id' ),
                array( 'node' => (string)$embargo->attribute( 'node_id' ), 'policy' => '!myshop/embargo_bypass' ),
                'notfound',
                array(), null, array(),
                'Embargoed until ' . date( 'c', $embargo->attribute( 'until' ) )
            );
        }
        return $rules;
    }
}

Provider laufen einmal pro Siteaccess und Prozess (die Engine wird behalten; siehe Abschnitt 14). Regeln, die sich im Laufe des Tages ändern, gehören in einen Fakt (Conditions[fact:embargoed]=1, pro Anfrage gelesen), nicht in einen Provider.

10.5 Alles registrieren

<?php /* #?ini charset="utf-8"?
# extension/myshop/settings/requestrules.ini.append.php

[RequestRuleSettings]
ConditionHandlers[customer_tier]=myShopCustomerTierCondition
ActionHandlers[paywall]=myShopPaywallAction
FactProviders[]=myShopFactProvider
RuleProviders[]=myShopRulesProvider
RuleList[]=premium_paywall

[Rule-premium_paywall]
Description=Premium articles for gold and silver customers; everyone else sees the paywall.
Conditions[class]=article
Conditions[fact:is_premium]=1
Conditions[customer_tier]=!gold,silver
Action=paywall
ActionArgs[template]=design:myshop/paywall.tpl
*/ ?>
php bin/php/ezpgenerateautoloads.php -e
php bin/php/ezrequestrules.php -s site --check --allow-root-user

10.6 Die Regeln Ihrer Erweiterung ohne Datenbank testen

Die Engine nimmt ihre Einstellungen als Array, und ein Kontext besteht nur aus Fakten:

$engine = new ezpRequestRuleEngine( array(
    'rules' => array( 'premium_paywall' => array(
        'Conditions' => array( 'class' => 'article', 'fact:is_premium' => '1', 'customer_tier' => '!gold,silver' ),
        'Action' => 'paywall' ) ),
    'condition_handlers' => array( 'customer_tier' => 'myShopCustomerTierCondition' ),
    'action_handlers' => array( 'paywall' => new myShopPaywallActionStub() ),
) );
$result = $engine->evaluate( new ezpRequestContext( array(
    'class_identifier' => 'article', 'is_premium' => true, 'customer_tier' => 'free',
) ) );
$this->assertSame( ezpRequestRuleResult::MODULE_RESULT, $result->type );
$this->assertSame( array(), $engine->validate() );

tests/tests/kernel/classes/requestrules/ezpRequestRuleEngineTest.php zeigt jede eingebaute Bedingung und Aktion auf diese Weise getestet.

11. Die Engine aus PHP verwenden

$engine = ezpRequestRuleEngine::instance();     // the current siteaccess's rules

// Add a rule at run time (idempotent by name: adding it again replaces it)
$engine->addRule( new ezpRequestRule( 'tmp_block', array( 'node' => '123' ), 'notfound' ) );
$engine->addRule( new ezpRequestRule( 'tmp_exception', array( 'node' => '123', 'role' => 'Editor' ), 'allow' ), 'tmp_block' );  // before tmp_block
$engine->removeRule( 'tmp_block' );

// Decide about any request, e.g. in a custom module or a script
$context = ezpRequestRuleKernel::context( 'content', 'view', array( 'full', '123' ),
                                          array( 'typed_uri' => 'content/view/full/123', 'via' => 'system' ),
                                          eZUser::currentUser() );
$result = $engine->evaluate( $context );       // ezpRequestRuleResult, or null: no rule decides
if ( $result ) echo $result->rule, ': ', $result->describe();

// Why
foreach ( $engine->explain( $context ) as $row )
    printf( "%s %s %s\n", $row['decides'] ? 'DECIDES' : ( $row['matched'] ? 'matched' : 'no' ), $row['rule'], json_encode( $row['conditions'] ) );

// Problems in the settings, as --check prints them
print_r( $engine->validate() );

ezpRequestRuleEngine::resetInstance();          // re-read requestrules.ini on the next instance()

Mit addRule() hinzugefügte Regeln leben so lange wie die Engine: eine Anfrage unter PHP-FPM oder die Lebensdauer eines Velocity-Workers. Verwenden Sie sie für Tests und Skripte. Regeln, die immer gelten müssen, gehören in die Einstellungen oder in einen Regel-Provider.

12. Prüfen, erklären und testen

12.1 bin/php/ezrequestrules.php

php bin/php/ezrequestrules.php -s site --list   --allow-root-user   # the rules, in order
php bin/php/ezrequestrules.php -s site --check  --allow-root-user   # problems; exit code 1 when any (for CI)
php bin/php/ezrequestrules.php -s site --uri=content/view/full/2 --allow-root-user
php bin/php/ezrequestrules.php -s site --uri=content/view/full/2 --user=admin --allow-root-user
php bin/php/ezrequestrules.php -s site --uri=fit-healthy --ip=10.1.2.3 --header=X-Requested-With:XMLHttpRequest --method=POST --allow-root-user

--uri übersetzt die Adresse so, wie es der Kernel tut (Alias, Wildcard, Startseite), sodass die Erklärung die ist, die eine echte Anfrage erhält. Sie sagt außerdem, wenn die Richtlinien die View ablehnen würden, bevor eine Regel gefragt wird.

Echte Ausgabe (Referenzinstallation, 2026-10-02):

Address  /content/view/full/2  ->  content/view/full/2  (requested via system)
User     anonymous (anonymous)  siteaccess site

DECIDES system_url_full_view_to_alias
        yes  requested_via = system
        yes  module_view = content/view
        yes  view_mode = full
        yes  policy = !content/view_system_url
        -> redirect 301 to /websites

Result   decided by the rule marked DECIDES
Facts the rules read:
  node_id              2
  requested_via        'system'
  typed_uri            'content/view/full/2'
  url_alias            'websites'
  ...

--check findet:

  • eine Regel in RuleList[] ohne ihre Gruppe;
  • eine Regel ohne Bedingungen oder Aktion;
  • unbekannte Namen von Bedingungen und Aktionen;
  • leere Werte;
  • param, header und fact ohne ihr :name;
  • Richtlinienwerte, die nicht Modul/Funktion sind;
  • redirect und rewrite ohne to;
  • Statuswerte, die keine Weiterleitungen sind;
  • Klassen von Handlern und Providern, die nicht existieren oder die falsche Schnittstelle implementieren.

Führen Sie es in Ihrer Deployment-Pipeline aus. Eine Regel mit einem Tippfehler passt nie; sie bringt die Website nicht zum Scheitern, daher ist --check der Weg, einen Tippfehler zu finden.

12.2 Zur Laufzeit

  • Debug-Ausgabe (DebugOutput=enabled): Jede Entscheidung ist ein Hinweis, Request rule 'name': redirect 301 to /x for content/view/full/2. Unbekannte Bedingungen und Aktionen sind Fehler.
  • $GLOBALS['ezpRequestRuleDecision']: das ezpRequestRuleResult, das über diese Anfrage entschieden hat, oder null. Verwenden Sie es in einem Operator des Pagelayouts oder in einem Response-Listener.
  • Action=log: var/log/requestrules.log.

12.3 Tests

php vendor/bin/phpunit tests/tests/kernel/classes/requestrules/    # 21 tests: every condition, action, the shipped file

Dieselben 21 Tests laufen mit den übrigen Kernel-Tests (--testsuite kernel-classes).

Durch Benutzung, über HTTP, gegen eine laufende Website: anonym und als Administrator, jede Aktion, Apache und Velocity. Überprüft am 2026-10-02 auf einer Referenzinstallation, alles PASS auf beiden Servern:

PrüfungApacheVelocity
anonyme System-URL → 301 auf den Alias, private, no-storePASSPASS
Benutzerparameter und Query bleiben erhaltenPASSPASS
Alias, Startseite, Listenansicht unberührtPASSPASS
Administrator behält die System-URL (200)PASSPASS
allow vor der ausgelieferten RegelPASSPASS
forbidden 403, notfound 404PASSPASS
redirect 307 auf ein Systemziel, als dessen Alias gesendetPASSPASS
rewrite behält die Adresse (200)PASSPASS
eine Umschreibschleife endet nach MaxRewrites (404)PASSPASS
log schreibt seine Zeile und gibt weiterPASSPASS
login → 302 auf user/login und nach der Anmeldung zurück zur SeitePASSPASS
nicht betroffene Seiten werden weiter aus den Seiten-Caches ausgeliefert (X-Exp-Cache: HIT)PASSPASS

13. Caches

Zwei Caches beantworten Anfragen, bevor der Kernel läuft, also bevor eine Regel gefragt wird: der rollenabhängige HTTP-Cache (sein früher Ausstieg in config.php) und der Antwort-Cache von Velocity. Die Regeln sind mit ihnen sicher, dank dreier Zusagen:

  1. Keine Antwort einer Regel außer allow wird gespeichert. Sie wird mit Cache-Control: private, no-store gesendet, was Velocity, Proxys und Browser beachten, und der HTTP-Cache lehnt sie ab (X-Exp-Cache: BYPASS (request rule)). Eine Weiterleitung für anonyme Besucher kann daher nie an einen Redakteur ausgeliefert werden, und ein Browser behält kein 301, das nach der Anmeldung noch gelten würde.
  2. Eine Seite, deren Regeln nur stabile Bedingungen lesen, wird wie bisher gecacht. Zwei Anfragen, die eine gespeicherte Seite beantwortet, haben dieselbe Adresse, denselben Siteaccess, Host, dasselbe Schema und denselben Berechtigungskontext, sodass die Regeln für beide gleich entscheiden. Die ausgelieferten Regeln sind alle stabil: Sie verringern das Caching überhaupt nicht (auf der Referenzinstallation bleibt /fit-healthy ein HIT).
  3. Eine Seite, über die eine Regel mit einer pro Anfrage veränderlichen Bedingung entscheiden könnte, wird nie gespeichert. Passt jede stabile Bedingung einer solchen Regel, könnte eine andere Anfrage für dieselbe Seite mit einem anderen Header, einer anderen Adresse oder einem anderen Benutzer anders entschieden werden. Daher wird die Seite mit private, no-store gesendet, auch wenn die View läuft, und der Kontextfakt rules_vary_by_request ist true. Stabile Bedingungen werden zuerst gefragt, sodass eine Regel wie module_view=content/view + header:X-Test=deny nur Seiten von content/view betrifft.

Leeren Sie nach dem Ändern von Regeln die Seiten-Caches. Eine Seite, die gespeichert wurde, bevor eine Regel existierte, wird ausgeliefert, ohne sie zu fragen. exp:velocity deploy tut das; andernfalls führen Sie php bin/php/ezcache.php --clear-id=content,exphttpcache --allow-root-user und ./console exp:velocity cache clear --apply aus.

Der View-Cache der Inhalte (ViewCaching) speichert die gerenderte Ansicht eines Knotens, nicht die Antwort. Er läuft nach den Regeln und ist von ihnen nicht betroffen.

14. Exponential Velocity und persistente Worker

  • Die Engine wird pro Siteaccess für die Lebensdauer des Workers behalten: requestrules.ini wird einmal pro Siteaccess gelesen, Regel-Provider laufen einmal, und Handler werden einmal erzeugt. Der Kontext ist für jede Anfrage neu.
  • Der Zustand pro Anfrage wird vom Kernel zu Beginn jeder Anfrage zurückgesetzt ($GLOBALS['ezpRequestRuleNoStore'], $GLOBALS['ezpRequestRuleDecision'], der Umschreibzähler). Die Entscheidung einer Anfrage kann nie in die nächste gelangen.
  • addRule() ist pro Name idempotent, sodass Code, der bei jeder Anfrage eine Regel hinzufügt, in einem lange laufenden Worker keine Regeln anhäuft.
  • Eine Änderung der Einstellungen erreicht Velocity erst nach einem Neustart. Worker behalten die INI, die sie geladen haben. Stellen Sie mit ./console exp:velocity deploy --no-autoload --allow-root-user bereit, das den INI-Cache leert, Velocity neu startet und die Seiten-Caches leert, in dieser Reihenfolge. PHP-FPM liest die Einstellungen erneut, sobald der INI-Cache geleert ist.
  • Neue Klassen für Bedingungen, Aktionen oder Provider brauchen neu erzeugte Autoloads der Erweiterungen (exp:velocity deploy erledigt das), und Kernel-Klassen brauchen --kernel.

15. Leistung

Gemessen auf einer Referenzinstallation (PHP 8.5, je 20 000 Auswertungen, ohne den Kernel; die Kosten schließen den Aufbau des Kontexts ein):

Regelnµs pro Anfrage
keine (der Standard)2,6
die ausgelieferte Regel, ein Alias, auf den sie nicht zutrifft9,7
die ausgelieferte Regel entscheidet (System-URL, liest den Alias des Knotens)23,3
20 Regeln, keine trifft zu110,5

Eine gerenderte Seite kostet auf demselben Server etwa 280 ms, daher machen selbst 20 Regeln 0,04 % davon aus. Eine aus einem Cache ausgelieferte Seite erreicht die Regeln überhaupt nicht. Die Zahlen stammen aus der Auswertung jedes Falls 20 000 Mal in einer Schleife mit einem vorbereiteten Kontext, so wie die Unit-Tests einen aufbauen.

Halten Sie Regeln günstig, indem Sie die Bedingungen innerhalb einer Regel von günstig nach teuer ordnen. Jede Bedingung muss passen, und die Auswertung endet bei der ersten, die nicht passt. Bedingungen zu Adresse, Modul, View und Benutzer kosten nichts; Bedingungen zum Knoten laden den Knoten einmal.

16. Hinweise zur Sicherheit

  • Regeln fügen Einschränkungen hinzu; Richtlinien gewähren Zugriff. Verlassen Sie sich nie auf eine Regel, um Daten zu schützen, die eine Richtlinie erlaubt. Die Regel kann ausgeschaltet, im falschen Siteaccess aufgeführt oder von einer View umgangen werden, an die niemand gedacht hat (Abschnitt 17). Schützen Sie Daten mit Einschränkungen von content/read; verwenden Sie Regeln dafür, wie erlaubte Inhalte erreicht werden dürfen.
  • Sicher für die Website, laut für den Betreiber. Eine unbekannte Bedingung passt nie, und eine unbekannte Aktion entscheidet nie, daher kann ein Tippfehler die Website nicht lahmlegen. Führen Sie --check aus, um Tippfehler zu finden.
  • Header und Client-Adressen kommen vom Client. header:* ist eine Bequemlichkeit, nie eine Authentifizierung. ip ist nur so vertrauenswürdig wie ClientIpByCustomHTTPHeader: Setzen Sie es nur hinter einem Proxy, der diesen Header überschreibt.
  • Weiterleitungen bleiben auf erlaubten Hosts. Ein absolutes Ziel auf einem anderen Host muss in AllowedRedirectHosts[] stehen; alles andere lehnt der Kernel ab. Platzhalter können mitbringen, was der Besucher gesendet hat ({typed_uri}, {host}, {header:...}); die Prüfung der erlaubten Hosts gilt trotzdem für das Ergebnis, sodass ein daraus gebautes Ziel Ihre Hosts nicht verlassen kann.
  • notfound verrät nichts. Es ist dieselbe Seite wie für einen Knoten, der nicht existiert. Verwenden Sie es statt forbidden, wenn schon die Existenz einer Seite vertraulich ist.
  • Keine Antwort, die davon abhängt, wer gefragt hat, wird gecacht (Abschnitt 13).

17. Was die Regeln nicht sehen

  • Adressen, die nie eine Modul-View erreichen:

    • ein Modul, das nicht existiert („nicht gefunden“ vor jeder Regel);
    • ein verschobener URL-Alias (der Kernel leitet zuerst auf die neue Adresse weiter);
    • durch [SiteAccessRules] ausgeschaltete Views;
    • Views, die die Richtlinien ablehnen.

    Um Adressen abzufangen, die nicht existieren, verwenden Sie URL-Wildcards.

  • Aus einem Seiten-Cache ausgelieferte Seiten. So gewollt, wie Abschnitt 13 erklärt.

  • Der Query-String. Kein Fakt enthält ihn (verwenden Sie einen Fakt-Provider, wenn Sie ihn brauchen). Benutzerparameter (/(offset)/10) sind Fakten.

  • Andere Einstiegspunkte: der Kernel der REST-API, index_treemenu.php, statische Dateien und Bild-Aliase, die der Webserver ausliefert, und CLI-Skripte.

  • Templates. Ein in eine andere Seite eingebetteter Knoten (node_view_gui, fetch) ist keine Anfrage; content/read regelt ihn.

18. Kompatibilität und Upgrade

  • Nichts ändert sich, bis eine Regel aufgeführt ist. RuleList[] ist in settings/requestrules.ini leer; die drei ausgelieferten Regeln sind definiert und ausgeschaltet.
  • [SiteAccessRules] funktioniert genau wie bisher und wird vor den Anfrageregeln geprüft (Abschnitt 3, Schritt 3).
  • Views aus PolicyOmitList[] werden ebenfalls gefragt. Die Regeln laufen für jede Modul-View, die läuft, ob ihre Richtlinie geprüft oder ausgelassen wird.
  • Die Richtlinienfunktion content/view_system_url erscheint im Rolleneditor; bestehende Rollen sind nicht betroffen. Rollen mit content/* schließen sie ein.
  • Klassennamen beginnen mit ezp, wie bei den anderen privaten Klassen des Kernels; sie sind ab 6.0.15 stabile API: ezpRequestRuleEngine, ezpRequestRule, ezpRequestRuleResult, ezpRequestContext, ezpRequestRuleCondition, ezpRequestRuleStableCondition, ezpRequestRuleAction, ezpRequestRuleProvider, ezpRequestFactProvider, ezpRequestFactCondition, ezpRequestRuleKernel. Eingebaute Klassen für Bedingungen und Aktionen können Geschwister erhalten; ihre Namen und ihr Verhalten bleiben.
  • Der Umweg über eine Weiterleitung im Template kann entfallen. Entfernen Sie eine Weiterleitung, die Sie zu diesem Zweck in full.tpl gesetzt haben, sobald die Regel eingeschaltet ist.

19. Fehlerbehebung

SymptomUrsacheLösung
Die Regel bewirkt nichtsnicht in RuleList[] für diesen Siteaccess; INI-Cache; Velocity nicht neu gestartet; Seite aus einem Cache ausgeliefert, der vor der Regel gespeichert wurde--list -s <sa>; exp:velocity deploy --no-autoload; content,exphttpcache leeren
--uri meldet DECIDES, der Browser 200der Browser oder ein Cache hat eine ältere Antwort behaltenversuchen Sie curl -sk -o /dev/null -w '%{http_code}'; leeren Sie die Seiten-Caches
Die ganze Website antwortet mit 404eine Regel ohne eingrenzende Bedingung (module_view / requested_via), z. B. nur Conditions[policy]=!...--uri= auf einen Alias zeigt, welche Regel entscheidet; grenzen Sie sie ein
Redakteure werden auf der öffentlichen Website von System-URLs weggeleitetihrer Rolle fehlt content/view_system_urlgewähren Sie sie (Abschnitt 8)
ERR_TOO_MANY_REDIRECTSein redirect, dessen Ziel auf dieselbe Regel passt (zum Beispiel to dieselbe Adresse)fügen Sie eine Bedingung hinzu, die das Ziel nicht erfüllt, oder verwenden Sie redirect_to_alias, das nie auf sich selbst weiterleitet
Umschreibungen enden in 404die umgeschriebene Adresse hat erneut gepasst; MaxRewrites erreichtschließen Sie das Ziel aus (Conditions[node]=!555)
Seiten einer Sektion werden nicht mehr gecachteine Regel dort verwendet header, ip, user_id, user_login, group, fact oder eine eigene Bedingung ohne Stabil-Markierungerwartet (Abschnitt 13); stellen Sie wenn möglich auf eine stabile Bedingung um
--check: "is not a class implementing"die Klasse fehlt in den Autoloads oder implementiert die falsche Schnittstellephp bin/php/ezpgenerateautoloads.php -e
Eine Entscheidung steht nicht in var/log/requestrules.lognur Action=log schreibt dorthinschalten Sie die Debug-Ausgabe ein oder setzen Sie eine Protokollregel davor

20. Dateien

DateiWas
settings/requestrules.iniEinstellungen, die drei ausgelieferten Regeln (ausgeschaltet)
kernel/private/classes/requestrules/ezprequestruleengine.phpdie Engine: Regeln, Handler, evaluate(), explain(), validate()
kernel/private/classes/requestrules/ezprequestrule.phpeine Regel; das Parsen von Schlüsseln und Werten
kernel/private/classes/requestrules/ezprequestcontext.phpdie Fakten einer Anfrage, bei Bedarf aufgelöst
kernel/private/classes/requestrules/ezprequestruleresult.phpdie Entscheidungen
kernel/private/classes/requestrules/ezprequestruleinterfaces.phpezpRequestRuleCondition, ezpRequestRuleStableCondition, ezpRequestRuleAction, ezpRequestRuleProvider, ezpRequestFactProvider
kernel/private/classes/requestrules/ezprequestruleconditions.phpdie eingebauten Bedingungen
kernel/private/classes/requestrules/ezprequestruleactions.phpdie eingebauten Aktionen
kernel/private/classes/requestrules/ezprequestrulekernel.phpdie Seite des Kernels: Fakten einer echten Anfrage, die Antwort auf eine Entscheidung
kernel/private/classes/ezpkernelweb.phphält fest, wie die Anfrage erreicht wurde; fragt die Regeln, bevor die View läuft
kernel/private/classes/httpcache/ezphttpcachelistener.phpspeichert keine Seite, die die Regeln aus gemeinsamen Caches heraushalten
kernel/content/module.phpdie Richtlinienfunktion content/view_system_url
bin/php/ezrequestrules.phpauflisten, prüfen, erklären
tests/tests/kernel/classes/requestrules/ezpRequestRuleEngineTest.php21 Unit-Tests

Verwandte Seiten

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x