Actionlogs in Joomla
Vroeg of laat stelt elke website-eigenaar een vraag die begint met "wie". Wie heeft gisteravond de homepage gedepubliceerd? Wie heeft die extensie geïnstalleerd die niemand herkent? Heeft de nieuwe redacteur echt twaalf artikelen verwijderd, of vergist de klant zich?
Zonder registratie hebben deze vragen geen antwoord en blijft je gissen.
Joomla beantwoordt ze met een kleine maar krachtige kerncomponent genaamd User Actions Log (com_actionlogs). Deze registreert stilletjes elke belangrijke wijziging op je site: opslaan, verwijderen, publiceren, inloggen, installeren en configuratiewijzigingen. Elke registratie bevat de gebruiker, de actie, het tijdstip en (optioneel) het IP-adres. Je hoeft niets te installeren. Het zit al in Joomla.
Wie wat deed, wanneer en vanaf waar, automatisch vastgelegd door Joomla zonder één enkele extensie van derden.
In dit artikel leggen we uit hoe de component Action Logs werkt, wat er wordt geregistreerd, hoe je het logboek kunt lezen en filteren, hoe meldingen en CSV-export werken en hoe je het logboek gezond houdt op een drukbezochte website. Het doel is om website-eigenaren, beheerders en ontwikkelaars voldoende inzicht te geven in deze stille getuige, zodat ze erop kunnen vertrouwen op de dag dat het nodig is.
1. De basis
1.1 Wat is het User Actions Log?
Het User Actions Log (com_actionlogs) is Joomla's ingebouwde auditlogcomponent. Joomla introduceerde deze in versie 3.9 (mei 2018) en sindsdien maakt deze standaard deel uit van de core.
Een aantal zaken maakt deze component bijzonder:
- Voor elke geregistreerde actie wordt één record opgeslagen in één tabel:
#__action_logs. - Het systeem werkt op basis van events, niet via polling. Elke actie genereert een Joomla-event, een plugin vangt dit op en schrijft een record weg.
- Elk record bevat de gebruiker, de tijdstempel, de extensiecontext, het item-ID, het IP-adres en een bericht gebaseerd op een taalstring.
- Het logboek is vanuit de interface alleen-lezen. Beheerders kunnen het bekijken, filteren, exporteren of opschonen, maar niet afzonderlijke records bewerken.
Dat laatste is belangrijk. Een auditlog die je kunt wijzigen is eigenlijk geen auditlog. Joomla biedt daarom bewust geen bewerkscherm voor logregels.
1.2 Een opmerking over de naamgeving: "Action Logs" versus "User Actions Log"
Voordat we verdergaan, is het goed om een veelvoorkomende bron van verwarring weg te nemen. Joomla gebruikt twee namen voor hetzelfde onderdeel, en die inconsistentie zorgt regelmatig voor verwarring:
| Waar je het ziet | Gebruikte naam |
|---|---|
| Menu-item in het beheer (J4 / 5 / 6) | Gebruikers → Actielogs |
| Titel van het helpscherm | User Actions Log: Opties |
| Koptekst van de lijstweergave | User Actions Log |
| Officiële documentatiesite | User Actions Log |
| Componentmap / interne naam | com_actionlogs |
| Naam van de registratieplugin | Action Log - Joomla (enkelvoud "Log") |
| Naam van de notificatieplugin | System - Action Logs (meervoud "Logs") |
"User Actions Log" is de formele, oorspronkelijke naam die Joomla in versie 3.9 aan deze functie gaf. Deze naam komt nog steeds voor in de helpdocumentatie en in de titelbalk. "Action Logs" is de kortere benaming die uiteindelijk in het beheermenu en in het dagelijks gebruik terechtkwam. Beide verwijzen naar dezelfde component, dezelfde databasetabellen en dezelfde plugins. Er bestaat geen aparte functie genaamd "User Action Logs".
Een historisch detail maakt de verwarring nog iets groter. In Joomla 3.9 en 3.10 stond het menu-item onder System → User Actions Log. Vanaf Joomla 4 verhuisde het naar Gebruikers → Actielogs. Oudere handleidingen en schermafbeeldingen tonen daarom nog de oude naam en locatie. In dit artikel betekenen "Action Logs" en "User Actions Log" hetzelfde. Bij twijfel is de officiële identificatie com_actionlogs.
1.3 Waar vind ik het?
In de Joomla 6-beheeromgeving zijn de volgende locaties relevant:
Gebruikers → Actielogs (de logviewer)
Gebruikers → Actielogs → Opties (instellingen + ACL)
Gebruikers → Meldingen Actielogs (e-mailmeldingen per gebruiker)
Systeem → Beheren → Plugins → Action Log - Joomla (de recorder)
Systeem → Beheren → Plugins → System - Action Logs (de notifier)
De component bevindt zich in administrator/components/com_actionlogs/. De twee plugins bevinden zich in plugins/actionlog/joomla/ (de recorder) en plugins/system/actionlogs/ (de notifier).
Een detail waar veel mensen over struikelen: de component staat onder Gebruikers en niet onder Systeem. Oudere schermafbeeldingen suggereren soms anders.
1.4 De drie onderdelen
Action Logs bestaat uit drie onderdelen die samenwerken:
| Onderdeel | Functie |
|---|---|
com_actionlogs |
Backend-lijstweergave, filters, CSV-export en opschonen. |
plg_actionlog_joomla |
Luistert naar events en schrijft logregels weg. |
plg_system_actionlogs |
Verstuurt meldingsmails en verwerkt berichten. |
Alle drie worden in Joomla 6 standaard ingeschakeld meegeleverd. Schakel je de recorder uit, dan wordt er niets meer geregistreerd. Schakel je de notifier uit, dan blijft het logboek groeien maar worden er geen e-mails meer verzonden.
1.5 Eerste kennismaking met het logboek
Open Gebruikers → Actielogs. De lijst wordt standaard gesorteerd op nieuwste eerst. Een typische regel ziet er als volgt uit:
| Kolom | Voorbeeld |
|---|---|
| Actie | Gebruiker article-editor heeft ingelogd in het beheer. |
| Datum | 2026-05-28 09:14:02 (relatief: "een paar seconden geleden") |
| Extensie | com_users |
| Gebruiker | admin |
| IP-adres | 10.10.10.1 (of "Uitgeschakeld" als IP-registratie uit staat) |
Klik op de actietekst en Joomla klapt de regel open. Je ziet dan het onderliggende berichtsjabloon en de JSON-gecodeerde context. Op die JSON komen we terug in sectie 6.
1.6 De lijst filteren
De filterbalk boven de lijstweergave biedt vier hulpmiddelen:
- Zoeken: vrije tekst op basis van het weergegeven bericht.
- Gebruiker: filter op activiteiten van één gebruiker.
- Extensie: alleen
com_content, alleencom_users, enzovoort. - Datumbereik: een begin- en einddatum selecteren.
De meest bruikbare combinatie is Gebruiker + Datumbereik. Daarmee beantwoord je de dagelijkse vraag "laat alles zien wat Alice afgelopen woensdag heeft gedaan" met slechts twee klikken.
Naar boven2. Wat wordt er gelogd?
2.1 De standaard gelogde extensies
U bepaalt zelf welke componenten worden gevolgd via Opties → Gelogde extensies. Dit is een meerkeuzelijst waarin standaard alle core-componenten zijn ingeschakeld:
com_banners com_cache com_categories com_checkin
com_config com_contact com_content com_fields
com_guidedtours com_installer com_media com_menus
com_messages com_modules com_newsfeeds com_plugins
com_redirect com_scheduler com_tags com_templates
com_users
Verwijder je een extensie uit deze lijst, dan worden de gebeurtenissen ervan stilzwijgend genegeerd. Er worden geen logregels meer aangemaakt. Het beperken van deze lijst is de meest effectieve manier om logvervuiling op een drukke website te verminderen.
2.2 Gebeurtenissen in de contentlevenscyclus
Voor elke logbare component abonneert de recorder-plugin zich op drie content-events:
| Event | Wat wordt gelogd |
|---|---|
onContentAfterSave |
Aanmaken of bijwerken, inclusief ID, titel en een nieuwe/bijgewerkte status. |
onContentAfterDelete |
Verwijderen, inclusief ID en titel (vastgelegd vóór verwijdering). |
onContentChangeState |
Publiceren, depubliceren, archiveren of naar de prullenbak verplaatsen, inclusief de nieuwe status. |
Elke keer dat je een artikel opslaat, een categorie verwijdert of een menu-item publiceert, wordt er dus een logregel aangemaakt.
2.3 Gebeurtenissen in de gebruikerslevenscyclus
Gebruikersgebeurtenissen zijn het belangrijkst voor het opsporen van misbruik van accounts:
| Event | Wat wordt gelogd |
|---|---|
onUserAfterLogin |
Succesvolle login (frontend of backend, maar nooit API-logins). |
onUserLoginFailure |
Mislukte login, maar alleen als de gebruikersnaam bestaat. |
onUserLogout |
Expliciet uitloggen. |
onUserAfterSave |
Aanmaken of bewerken van een gebruiker (inclusief groepswijzigingen). |
onUserAfterDelete |
Verwijderen van een gebruiker. |
onUserAfterRemind |
Aanvraag voor "Gebruikersnaam vergeten". |
onUserAfterResetRequest |
Aanvraag voor een wachtwoordresetlink. |
onUserAfterResetComplete |
Voltooien van een wachtwoordreset. |
Een detail dat veel mensen verrast: mislukte logins met een onbekende gebruikersnaam worden niet gelogd. De plugin controleert eerst of de gebruiker bestaat, waardoor geautomatiseerde scans en bots niet in het auditlog terechtkomen.
2.4 Gebeurtenissen rond extensies
Alles wat wijzigingen aanbrengt in de extensietabel wordt geregistreerd:
| Event | Wat wordt gelogd |
|---|---|
onExtensionAfterInstall |
Installatie, inclusief type, naam en versie. |
onExtensionAfterUpdate |
Update van oude naar nieuwe versie. |
onExtensionAfterUninstall |
Deïnstallatie. |
onExtensionAfterSave |
Bewerking, bijvoorbeeld het in- of uitschakelen van een plugin. |
onJoomlaAfterUpdate |
Bijwerken van de Joomla-coreversie. |
Dit is bijzonder waardevol bij onderzoek na een incident. De vraag "wanneer hebben we die kwetsbare plugin geïnstalleerd?" is dan met één zoekopdracht te beantwoorden.
2.5 Configuratiewijzigingen
Joomla registreert ook het opslaan van configuraties:
onApplicationAfterSave: de Algemene Configuratie is opgeslagen.onExtensionAfterSavemet contextcom_config.component: het Opties-scherm van een component is opgeslagen.
In beide gevallen wordt vastgelegd welke instellingengroep is gewijzigd, maar niet welke waarden precies zijn veranderd. Als je een exacte vergelijking tussen oude en nieuwe waarden nodig heeft, is daarvoor een kleine maatwerkplugin nodig (zie sectie 11).
2.6 Operationele gebeurtenissen
Ook enkele onderhoudsacties worden geregistreerd:
| Event | Wat wordt gelogd |
|---|---|
onAfterCheckin |
Een beheerder heeft een vergrendeld item geforceerd ingecheckt. |
onAfterPurge |
De cache is geleegd. |
onAfterLogPurge |
Het actielogboek is opgeschoond. |
onAfterLogExport |
Een CSV-export is gedownload. |
Ja, het opschonen van het logboek wordt zelf ook gelogd. Na een opschoning blijft er precies één regel over: "Gebruiker admin heeft de actielogs opgeschoond." Het auditspoor documenteert zichzelf.
2.7 API-verzoeken (optioneel)
Als je Opties → API-endpoints loggen = Ja inschakelt, registreert Joomla iedere Web Services API-aanroep tijdens de verwerking. Met een tweede optie, Gelogde HTTP-methoden, bepaal je welke verzoektypen worden vastgelegd. Standaard staat alleen GET aan, maar op productiesites kiest men meestal minimaal ook voor POST, PUT, PATCH en DELETE.
Een waarschuwing: API-logging vult de tabel erg snel. Schakel het in tijdens een onderzoek en schakel het daarna weer uit voor normaal gebruik. In sectie 8 bekijken we de impact op de omvang van het logboek.
Naar boven3. Meldingen
3.1 Het opt-inmodel
Elke gebruiker kan zich aanmelden voor e-mailmeldingen van één of meer extensies via Gebruikers → Meldingen Actielogs. Deze voorkeuren worden opgeslagen in #__action_logs_users:
user_id notify (0/1) extensions (komma-gescheiden lijst met contexten)
- Een gebruiker die niet in deze tabel voorkomt, ontvangt geen meldingen.
- Een gebruiker met
notify = 1enextensions = com_users,com_installerontvangt een e-mail telkens wanneer iemand gebruikers of extensies wijzigt.
Meldingen zijn een persoonlijke keuze per gebruiker en geen sitebrede instelling. Power users en security officers melden zich aan, terwijl andere gebruikers geen berichten ontvangen.
3.2 Hoe ziet de e-mail eruit?
De notifier gebruikt hetzelfde leesbare bericht als in de lijstweergave, aangevuld met:
- Een directe link naar het betreffende item, indien beschikbaar.
- De naam van de gebruiker die de actie uitvoerde.
- Een link naar de betreffende logregel.
De e-mail wordt verzonden via de ingestelde mailserver. Controleer daarom de configuratie onder Systeem → Algemene Configuratie → Server → E-mail voordat je op meldingen vertrouwt. In een lokale Docker-omgeving kan een tool zoals MailHog alle uitgaande berichten opvangen zodat je veilig kunt testen.
3.3 De rol van de systeemplugin
Het helpt om de twee plugins duidelijk uit elkaar te houden:
- De plugin Action Log - Joomla schrijft uitsluitend logregels weg.
- De plugin System - Action Logs verzorgt meldingen per e-mail en de verwerking van berichten.
Als je de systeemplugin uitschakelt, blijft het logboek gewoon groeien en blijven de berichten zichtbaar, maar worden er geen meldingsmails meer verstuurd. Laat beide plugins in productie ingeschakeld. Schakel de systeemplugin alleen tijdelijk uit als je e-mailstormen wilt voorkomen tijdens een grote migratie.
Naar boven4. Exporteren en opschonen
4.1 CSV-export
De lijstweergave bevat twee exportknoppen in de werkbalk:
| Knop | Wat wordt geëxporteerd |
|---|---|
| Geselecteerde exporteren | Alleen de regels die je hebt geselecteerd. |
| Alles exporteren | Het volledige logboek, rekening houdend met de actieve filters. |
Het scheidingsteken is instelbaar via Opties → CSV-scheidingsteken. Kies een puntkomma (;) als je spreadsheetprogramma (zoals de Nederlandse versie van Excel) komma's als decimaalteken gebruikt.
De export wordt streamend uitgevoerd, één regel tegelijk. Daardoor raakt zelfs een logboek met een miljoen records niet door het beschikbare PHP-geheugen heen.
4.2 Bescherming tegen CSV-injectie
Joomla ontsnapt automatisch elke cel die begint met =, +, -, @, een tabteken of een carriage return door er een enkele apostrof voor te plaatsen. Dit voorkomt de klassieke aanval via "Excel-formule-injectie", waarbij een gelogde gebruikersnaam zoals =cmd|'/c calc'!A1 anders als formule zou worden uitgevoerd zodra een beheerder het CSV-bestand opent.
Als je ooit een eigen exportfunctie ontwikkelt, behoud deze beveiliging. Die is er met een goede reden.
4.3 Het logboek opschonen
Met de knop Opschonen in de werkbalk verwijder je alle records uit #__action_logs. Daarna schrijft Joomla direct één nieuwe logregel weg, zodat er altijd één record overblijft waarin staat wie het logboek heeft opgeschoond en wanneer.
Veelvoorkomende redenen om het logboek op te schonen:
- Na een langdurige migratieperiode, wanneer je met een schone lei wilt beginnen.
- Voordat je uitsluitend recente activiteiten wilt exporteren.
Er is geen mogelijkheid om dit ongedaan te maken en Joomla bevat geen ingebouwde functie voor automatisch opschonen. Voor geautomatiseerde opruiming kun je een Taakplanner-taak gebruiken (zie sectie 8).
Naar boven5. IP-logging en privacy
5.1 Standaardinstelling: IP-logging uitgeschakeld
Standaard staat Opties → IP-logging = Nee. Wanneer IP-logging is uitgeschakeld, wordt in iedere logregel een tijdelijke aanduiding opgeslagen in plaats van een echt IP-adres en toont de lijstweergave "Uitgeschakeld".
Wanneer je IP-logging inschakelt, leest Joomla het IP-adres van de bezoeker uit en houdt het rekening met de headers X-Forwarded-For en X-Real-IP wanneer het verzoek afkomstig is van een vertrouwde proxy. Vertrouwde proxyservers configureer je via Algemene Configuratie → Server. Als de gevonden waarde geen geldig IP-adres is, wordt in het logboek "Invalid" opgeslagen.
5.2 AVG-overwegingen
Een IP-adres is volgens de AVG (GDPR) persoonsgegeven. Wanneer je IP-logging inschakelt, moet je daarom rekening houden met het volgende:
- Zorg voor een geldige grondslag. Gerechtvaardigd belang voor beveiliging is meestal voldoende.
- Vermeld IP-logging in je privacyverklaring.
- Definieer een bewaartermijn. Het onbeperkt bewaren van IP-adressen is lastig te rechtvaardigen.
Praktische standaardinstellingen voor een publieke Joomla-website:
- IP-logging ingeschakeld, je zult blij zijn dat je het hebt wanneer er ooit een beveiligingsincident plaatsvindt.
- Een bewaartermijn van ongeveer 90 dagen, verwijder oudere records automatisch via een Taakplanner-taak.
- Een vermelding in de privacyverklaring onder het kopje "Beveiligingslogboeken".
5.3 Verzoeken op grond van het recht om vergeten te worden
Wanneer een gebruiker vraagt om verwijdering van zijn gegevens, hoef je niet het volledige auditspoor te vernietigen. Anonimiseren is meestal voldoende:
- Verwijder de gebruiker via
com_users. Hierdoor wordt nog één laatste logregel aangemaakt waarin naar het verwijderde account-ID wordt verwezen. - Voer vervolgens een SQL-update uit om historische gegevens te anonimiseren:
UPDATE jos_action_logs
SET user_id = 0,
ip_address = '0.0.0.0',
message = REPLACE(message, 'OldUsername', 'deleted-user')
WHERE user_id = 123;
Het auditspoor blijft intact, alleen de persoonlijk identificeerbare gegevens worden verwijderd. Vervang jos_ door het daadwerkelijke databasevoorvoegsel van je website.
6. Onder de motorkap
6.1 De vier tabellen
Action Logs gebruikt vier databasetabellen:
#__action_logs één record per gelogde actie
#__action_logs_extensions de lijst met deelnemende extensies
#__action_log_config hoe elk contenttype wordt weergegeven
#__action_logs_users meldingsvoorkeuren per gebruiker
De belangrijkste tabel is #__action_logs. De drie andere zijn relatief kleine referentietabellen.
6.2 De hoofdlogtabel
De belangrijkste velden van #__action_logs zijn:
id auto-increment primaire sleutel
message_language_key sjabloonsleutel, bijvoorbeeld PLG_ACTIONLOG_JOOMLA_CONTENT_UPDATED
message JSON met de plaatsvervangende waarden
log_date tijdstip waarop de actie plaatsvond
extension context, bijvoorbeeld com_content.article
user_id uitvoerende gebruiker (0 = gast of systeem)
item_id ID van het betrokken item (0 indien niet van toepassing)
ip_address echt IP-adres, "Disabled" of "Invalid"
De tabel bevat verschillende indexen op user_id, (user_id, log_date), (user_id, extension) en (extension, item_id). Dankzij deze indexen blijft een filter zoals "toon alle acties van gebruiker X" snel werken, zelfs wanneer het logboek miljoenen records bevat.
6.3 De JSON-berichtenstructuur
Hier wordt het interessant. De kolom message bevat niet de uiteindelijke tekst die je in het logboek ziet. In plaats daarvan bevat deze een JSON-object met plaatsvervangende waarden:
{
"action": "update",
"type": "PLG_ACTIONLOG_JOOMLA_TYPE_ARTICLE",
"id": 42,
"title": "About Us",
"itemlink": "index.php?option=com_content&task=article.edit&id=42",
"userid": 100,
"username": "admin",
"accountlink": "index.php?option=com_users&task=user.edit&id=100"
}
De message_language_key verwijst naar een sjabloon, bijvoorbeeld:
"User {username} updated {type} {title}."
Tijdens het weergeven vervangt Joomla de JSON-waarden door de daadwerkelijke gegevens en maakt het van de gebruikersnaam en titel klikbare links. Dit is precies waarom het logboek vertaalbaar is: het bericht bestaat uit een sleutel en niet uit een vaste tekst. Installeer je het Nederlandse taalpakket, dan verandert "User admin updated..." automatisch in "Gebruiker admin heeft ... bijgewerkt."
6.4 De contenttype-mapping
De tabel #__action_log_config vertelt de renderer hoe elk contenttype moet worden verwerkt. Voor ieder type wordt vastgelegd welke kolom het ID bevat, welke kolom de titel bevat, welke tabel gebruikt wordt en welke tekstprefix nodig is om de juiste taalstring op te bouwen:
type_alias id_holder title_holder table_name
com_content.article id title #__content
com_categories.category id title #__categories
com_redirect.link id old_url #__redirect_links
com_modules.module id title #__modules
...ongeveer 23 regels in Joomla 6
Een maatwerkcomponent kan zijn eigen contenttype registreren door hier een extra record toe te voegen. Ontwikkelaars gebruiken dit mechanisme om hun eigen extensies compatibel te maken met Action Logs (zie sectie 11).
Naar boven7. Rechten en toegang
7.1 ACL-acties
Onder Opties → Rechten vind je de standaard componentrechten:
| Actie | Wat wordt beheerd |
|---|---|
| Configureren | De componentinstellingen wijzigen. |
| Toegang tot beheerinterface | De lijstweergave van Action Logs openen. |
| Verwijderen | Het logboek opschonen. |
Opvallend is wat ontbreekt: er bestaat geen recht voor Aanmaken en geen recht voor Bewerken. Je kunt via de interface geen logregels handmatig toevoegen of wijzigen. Dat is een bewuste ontwerpkeuze.
7.2 Wie zou toegang moeten hebben?
Een logische rechtenstructuur ziet er ongeveer zo uit:
| Rol | Bekijken | Opschonen |
|---|---|---|
| Super User | Ja | Ja |
| Security officer (alleen-lezen groep) | Ja | Nee |
| Contentredacteur | Nee | Nee |
De configuratie "wel bekijken maar niet opschonen" is het klassieke auditofficier-model. Geef een aparte groep het recht Toegang tot beheerinterface, maar niet het recht Verwijderen. Zo kunnen zij alles controleren zonder iets te kunnen wijzigen.
Naar boven8. Prestaties en schaalbaarheid
8.1 Hoe snel groeit het logboek?
Voor een gemiddeld contentteam blijft het logboek relatief klein. Een team van vijf redacteuren genereert bijvoorbeeld ongeveer:
~50 artikelwijzigingen per dag + ~20 menu-/modulewijzigingen per dag + ~10 logins per dag
= ongeveer 80 records per dag = ~2.400 records per maand = ~30.000 records per jaar
Elke logregel neemt ongeveer 500 bytes in beslag. Eén jaar aan gegevens komt daarmee neer op circa 15 MB. Dat vormt geen enkel probleem.
API-logging verandert dit beeld volledig. Een website die via de API gemiddeld 10 verzoeken per seconde verwerkt, genereert al snel 864.000 logregels per dag. Schakel deze functie daarom niet zonder goede reden in.
8.2 Strategieën voor opschonen
Een Taakplanner-taak is de meest nette manier om het logboek beheersbaar te houden. Een eenvoudige opschoontaak verwijdert alles wat ouder is dan 90 dagen:
DELETE FROM jos_action_logs
WHERE log_date < NOW() - INTERVAL 90 DAY;
Een slimmere aanpak bewaart beveiligingsrelevante gebeurtenissen langer en verwijdert alleen routinematige contentwijzigingen:
DELETE FROM jos_action_logs
WHERE log_date < NOW() - INTERVAL 90 DAY
AND extension NOT IN ('com_users', 'com_installer', 'com_config');
Logins, extensie-installaties en configuratiewijzigingen zijn doorgaans waardevoller voor forensisch onderzoek dan gewone opslagacties. Hun belang neemt vaak juist toe naarmate ze ouder worden.
8.3 Snelle en trage query's
Dankzij de aanwezige indexen blijven query's die filteren op gebruiker, datum, extensie of item-ID snel:
-- Snel: alle acties van één gebruiker in de afgelopen 7 dagen
SELECT * FROM jos_action_logs
WHERE user_id = 100 AND log_date > NOW() - INTERVAL 7 DAY
ORDER BY log_date DESC;
Vrije-tekstzoekopdrachten in het JSON-bericht beschikken echter over geen bruikbare index en moeten de volledige tabel doorzoeken:
-- Traag: vrije-tekstzoekactie in het bericht
SELECT * FROM jos_action_logs
WHERE message LIKE '%phishing%';
De zoekfunctie in de lijstweergave gebruikt precies zo'n LIKE '%...%'-query. Voor incidenteel gebruik door een beheerder is dat prima, maar gebruik dit niet als basis voor geautomatiseerde monitoring of polling.
8.4 Praktische SQL-query's voor onderzoek
Mislukte logins van gisteren, een handige indicator voor brute-force-aanvallen:
SELECT user_id, COUNT(*) AS attempts
FROM jos_action_logs
WHERE message_language_key = 'PLG_ACTIONLOG_JOOMLA_USER_LOGIN_FAILED'
AND log_date > NOW() - INTERVAL 1 DAY
GROUP BY user_id
HAVING attempts > 5
ORDER BY attempts DESC;
Recente extensie-installaties, een nuttige controle op ongewenste software:
SELECT log_date, user_id, message
FROM jos_action_logs
WHERE extension = 'com_installer'
AND log_date > NOW() - INTERVAL 7 DAY
ORDER BY log_date DESC;
Vergeet niet jos_ te vervangen door het daadwerkelijke databasevoorvoegsel van je Joomla-installatie.
9. Veelvoorkomende fouten en valkuilen
9.1 "Er wordt niets gelogd"
Doorloop deze controlelijst in volgorde:
- Is de plugin Action Log - Joomla ingeschakeld?
- Staat de betreffende component in de lijst Gelogde extensies?
- Is de actie daadwerkelijk geslaagd? De recorder werkt met "after"-events, dus een opslagactie die faalt door validatiefouten wordt niet geregistreerd.
- Controleer je het juiste datumbereik in de filters?
9.2 "Niet alle mislukte logins worden gelogd"
Dat is bewust zo ontworpen. De plugin negeert mislukte inlogpogingen voor niet-bestaande gebruikersnamen om te voorkomen dat geautomatiseerde scanners de tabel vullen met nutteloze gegevens. Alleen mislukte pogingen voor bestaande gebruikers worden geregistreerd.
9.3 "Artikelwijzigingen worden dubbel gelogd"
Dit is geen fout. De recorder luistert naar onContentAfterSave voor zowel het backend-bewerkscherm (com_content.article) als het frontend-inzendformulier (com_content.form). Hetzelfde event wordt dus in verschillende contexten gebruikt. Controleer de kolom extension om te zien welke context de gebeurtenis heeft veroorzaakt.
9.4 "De weergegeven gebruiker heeft de actie niet uitgevoerd"
De recorder registreert de gebruiker die op het moment van de gebeurtenis is geauthenticeerd. CLI-scripts en Taakplanner-taken draaien als gastgebruiker en verschijnen daarom met user_id = 0.
Een waarde van user_id = 0 betekent meestal één van de volgende situaties:
- Een niet-geauthenticeerde frontendactie, zoals een verzoek voor een wachtwoordreset.
- Een geplande taak of CLI-commando.
- Een maatwerkplugin die buiten een HTTP-verzoek wordt uitgevoerd.
De kolom extension en, indien ingeschakeld, het IP-adres helpen meestal om het verschil tussen deze situaties te herkennen.
9.5 "Het bericht toont 'User undefined updated ...'"
Dit wijst op een ontbrekende taalstring. Dat gebeurt wanneer een maatwerkextensie wel een event genereert maar geen bijbehorende PLG_ACTIONLOG_...-taalstrings bevat, of wanneer de actieve taalvertaling de betreffende sleutel mist.
De oplossing is het toevoegen van de ontbrekende taalstring aan het taalbestand of het registreren van de juiste prefix in #__action_log_config.
9.6 "Opschonen heeft mijn bewijsmateriaal verwijderd"
Er bestaat geen mogelijkheid om een opschoning ongedaan te maken. Voordat je ooit het logboek opschoont:
- Maak eerst een CSV-export via de knop Alles exporteren.
- Bewaar het CSV-bestand buiten de Joomla-installatie.
- Voer pas daarna de opschoning uit.
Voor websites die moeten voldoen aan compliance- of auditvereisten geldt een eenvoudige regel: verwijder nooit loggegevens zonder eerst een export te maken en vast te leggen wie de opschoning heeft uitgevoerd.
9.7 "Ik kan Action Logs niet vinden in het menu"
De component bevindt zich onder Gebruikers en niet onder Systeem. Daarnaast verbergt Joomla automatisch de menulink voor gebruikers die niet beschikken over het recht Toegang tot beheerinterface. Een gewone redacteur zal de optie daarom simpelweg niet zien.
Naar boven10. Beveiliging en compliance
10.1 Het auditspoor is zelf ook een doelwit
Een aanvaller die beheerderstoegang verkrijgt, wil vaak niet alleen iets kwaadaardigs uitvoeren, maar ook de sporen wissen. Het actielogboek maakt dat moeilijker, maar biedt geen volledige garantie. Een Super User kan het logboek opschonen, de recorder uitschakelen of zelfs afzonderlijke records verwijderen via directe SQL-opdrachten.
Verstandige maatregelen zijn onder meer:
- Beperk het recht Verwijderen tot één speciaal beveiligingsaccount.
- Sla loggegevens ook extern op, zodat de lokale kopie niet de enige bron van waarheid is.
- Controleer actief op meta-gebeurtenissen, zoals het opschonen van het logboek of het uitschakelen van de recorder-plugin.
Ook je eigen beheerders verdienen controle. Het logboek is een afschrikmiddel en een forensisch hulpmiddel, geen absolute garantie.
10.2 Loggegevens omzetten in actie
Een logboek dat je pas achteraf bekijkt benut slechts de helft van zijn waarde. Action Logs kunnen ook gebruikt worden als basis voor automatische detectie en waarschuwingen:
- Waarschuwingen bij brute-force-aanvallen: een Taakplanner-taak voert periodiek de query voor mislukte logins uit en verstuurt een melding via Slack of e-mail zodra een drempelwaarde wordt overschreden.
- Meldingen bij verdachte installaties: een webhook die reageert op extensie-installaties en direct het beveiligingsteam informeert. Een plugin-installatie om 03:00 uur door een beheerder die normaal alleen overdag werkt, is bijvoorbeeld verdacht.
- Bewaking van privilege-escalatie: een melding wanneer iemand wordt toegevoegd aan de groep Super Users. Dit hoort slechts zelden voor te komen.
Het actielogboek vormt je detectielaag. Combineer het met een reactielaag, bijvoorbeeld via Joomla-plug-ins, Taakplanner-taken of een extern monitoringsysteem.
10.3 Een minimale maar effectieve beveiligingsconfiguratie
Voor een productiewebsite die echt belangrijk is, levert ongeveer twintig minuten configuratiewerk veel extra veiligheid op:
- Action Logs inschakelen voor
com_users,com_installer,com_config,com_plugins,com_modulesencom_templates. - IP-logging inschakelen en een bewaartermijn van 90 dagen instellen via een geplande taak.
- Meldingen inschakelen voor Super User-accounts, met toezicht op
com_usersencom_installer. - Het recht Verwijderen beperken tot één speciaal beveiligingsaccount.
- Dagelijks de query voor mislukte logins controleren, of een dashboard gebruiken dat dezelfde informatie toont.
De investering betaalt zich terug zodra iemand probeert slimmer te zijn dan het systeem.
Naar boven11. Aanpassingen voor ontwikkelaars
11.1 Een eigen component registreren voor logging
U kunt een eigen component compatibel maken met Action Logs in twee stappen, zonder een aparte plugin te schrijven. Voeg de component eerst toe aan de lijst met logbare extensies:
INSERT INTO jos_action_logs_extensions (extension)
VALUES ('com_mycomponent');
Voeg vervolgens één of meer contenttype-definities toe zodat Joomla weet hoe berichten moeten worden opgebouwd:
INSERT INTO jos_action_log_config
(type_title, type_alias, id_holder, title_holder, table_name, text_prefix)
VALUES
('myitem', 'com_mycomponent.item', 'id', 'name',
'#__mycomponent_items', 'PLG_ACTIONLOG_MYCOMPONENT');
Lever daarna taalstrings mee die beginnen met PLG_ACTIONLOG_MYCOMPONENT_... voor iedere actie die je wil registreren. Zolang je component standaardevents zoals onContentAfterSave en vergelijkbare gebeurtenissen uitzendt met de juiste context, verwerkt de bestaande recorder-plugin de rest automatisch.
11.2 Logregels vanuit eigen code toevoegen
Voor een eenmalige logregel vanuit een controller, model of importscript kun je rechtstreeks het Action Logs-model gebruiken:
$model = $this->app->bootComponent('com_actionlogs')
->getMVCFactory()
->createModel('Actionlog', 'Administrator');
$model->addLog(
[['action' => 'custom', 'detail' => 'Handmatige registratie vanuit importscript']],
'COM_MYCOMPONENT_LOG_IMPORT_RAN',
'com_mycomponent.import',
$userId // 0 = huidige gebruiker
);
Dit is bijzonder handig voor batchprocessen of importscripts die een spoor in het auditlog moeten achterlaten zonder gebruik te maken van het eventsysteem.
11.3 Geautomatiseerd opschonen
Joomla bevat geen ingebouwd bewaarbeleid voor Action Logs, maar met de Taakplanner kun je dat in enkele minuten zelf regelen. Ga naar Systeem → Beheren → Taken → Nieuw en maak een database-opruimtaak aan:
| Veld | Waarde |
|---|---|
| Titel | Action Logs opschonen |
| Taak | Database-opruiming, SQL-bewerkingen |
| Query | DELETE FROM #__action_logs WHERE log_date < NOW() - INTERVAL 90 DAY |
| Schema | Cron-notatie: 0 3 * * * (elke nacht om 03:00 uur) |
De Taakplanner voert deze opschoning vervolgens automatisch uit. Voor de meest betrouwbare werking is het verstandig de Taakplanner te activeren via een echte cronjob op de server, in plaats van afhankelijk te zijn van websiteverkeer.
Naar boven12. Action Logs versus andere logbestanden
12.1 Action Logs versus het systeemlogboek
Joomla beschikt ook over een technisch systeemlogboek dat wordt gevuld via Log::add(). Beide logsystemen hebben een ander doel:
| Aspect | Action Logs | Systeemlogboek |
|---|---|---|
| Gebruiksvriendelijke interface | Ja | Nee, tekstbestanden |
| Opslaglocatie | Database | Bestanden |
| Vertaalbare berichten | Ja | Nee |
| Meldingen per gebruiker | Ja | Nee |
| Beste toepassing | Audittrail voor contentbeheer (wie deed wat) | Technische gebeurtenissen (fouten, prestaties) |
Gebruik Action Logs om te achterhalen wie wat heeft gedaan binnen Joomla. Gebruik het systeemlogboek voor technische gebeurtenissen. Beide vullen elkaar aan.
12.2 Action Logs versus serverlogs
Action Logs werken op het niveau van de applicatie. Alles wat het Joomla-eventsysteem niet bereikt, blijft onzichtbaar voor het actielogboek. Voor een compleet beeld heb je daarom ook de infrastructuurlaag nodig:
| Laag | Wat wordt gezien | Wat ontbreekt |
|---|---|---|
| Action Logs | CRUD-acties, logins, installaties, configuratiewijzigingen, wie deed wat | Verzoeken die niet zijn verwerkt, PHP-fatals, serverblokkades |
| Apache/nginx access log | Elk HTTP-verzoek: URL, statuscode, IP-adres en user-agent | De Joomla-gebruiker, het betrokken item en de intentie |
| PHP-foutenlogboek | Fatals, waarschuwingen en stacktraces | Succesvolle acties en gebruikersidentiteit |
Een voorbeeld maakt het verschil duidelijk. Een artikel dat een HTTP 500-fout veroorzaakt verschijnt in het PHP-foutenlogboek en in het access log, maar niet in Action Logs, omdat het opslag-event nooit werd uitgevoerd. Het omgekeerde geldt ook: een redacteur die stilletjes een pagina naar de prullenbak verplaatst, verschijnt duidelijk in Action Logs, terwijl het access log slechts een gewone POST-aanvraag met statuscode 200 laat zien.
Voor serieus forensisch onderzoek combineer je tijdstempels uit al deze bronnen. Action Logs beantwoorden de vraag wie, serverlogs beantwoorden de vraag hoe het verzoek binnenkwam. Samen vertellen ze wat er werkelijk is gebeurd.
Naar boven13. Best practices
Als je slechts een paar dingen uit dit artikel onthoudt, laat het dan deze zijn:
- Laat beide Action Logs-plug-ins ingeschakeld op productiewebsites.
- Beperk de lijst met gelogde extensies om ruis op drukke websites te verminderen.
- Schakel IP-logging in, maar combineer dit met een bewaartermijn en een vermelding in de privacyverklaring.
- Voer nooit een opschoning uit zonder eerst een CSV-export veilig buiten Joomla op te slaan.
- Beperk het recht Verwijderen tot één speciaal beveiligingsaccount.
- Laat API-logging uitgeschakeld tenzij je actief onderzoek doet naar een probleem of incident.
14. In het kort
COMPONENT Gebruikers → Action Logs
MELDINGEN Gebruikers → Meldingen Action Logs
OPTIES Gebruikers → Action Logs → Opties
RECORDER Systeem → Plugins → Action Log - Joomla
NOTIFIER Systeem → Plugins → System - Action Logs
HOOFDTABEL #__action_logs
GELOGDE EXTS Opties → Gelogde extensies (standaard 21)
IP-LOGGING Opties → IP-logging (standaard UIT)
API-LOGGING Opties → API-endpoints loggen (standaard UIT)
EXPORT Werkbalk → Alles exporteren / Geselecteerde exporteren
OPSCHONEN Werkbalk → Opschonen (geen undo, wordt zelf gelogd)
RETENTIE com_scheduler → SQL Operations-taak
SINDS Joomla 3.9 (mei 2018)
Naar boven15. Samenvatting
Het User Actions Log is een van die Joomla-functies die weinig vraagt en veel oplevert. Het draait stil op de achtergrond, registreert iedere betekenisvolle wijziging en bewijst zijn waarde zodra een klant vraagt: "wie heeft de homepage gedepubliceerd?"
Met slechts enkele minuten configuratiewerk krijgt u:
- Direct inzetbare auditing voor 21 core-componenten, zonder extra extensies.
- Vertaalde en leesbare berichten die worden opgebouwd uit JSON-placeholders.
- Meldingen per gebruiker met gedetailleerde opt-inmogelijkheden.
- CSV-export met bescherming tegen formule-injecties voor veilig gebruik in spreadsheets.
- Optionele IP-logging die standaard privacyvriendelijk is ingesteld.
- Een geïndexeerde databasestructuur die moeiteloos miljoenen records aankan.
Het systeem is niet perfect. Het biedt op zichzelf geen bescherming tegen manipulatie en een vastberaden Super User kan nog steeds rechtstreeks wijzigingen in de database aanbrengen. Maar als detectielaag, gecombineerd met doordachte rechtenstructuren en een goed responsplan, verandert het de situatie van "we hebben geen idee wat er is gebeurd" naar "dit is precies wie wat heeft gedaan, en wanneer".
Beheer je een Joomla-website die belangrijk voor je is, schakel Action Logs dan in, stem de instellingen af op je situatie en leer het logboek lezen voordat je het echt nodig hebt.
Naar boven

Joomla specialist en Linux admin voor snelle, veilige en schaalbare websites.


