Der Standard-Anmeldebildschirm von WordPress (wp-login.php) ist in drei Sekunden erkennbar: grauer Hintergrund, WordPress-Logo, generisches Formular. Für einen Hobby-Blog ist das in Ordnung. Für einen Shop, ein Kundenportal oder ein Agenturprojekt unter der Marke des Kunden ist es ein Branding-Fehler. Redakteure melden sich täglich an, und ihr erster Eindruck ist nicht die Startseite, sondern dieser Bildschirm.
Dieser Leitfaden zeigt, wie Sie das Login ausschließlich mit WordPress-Hooks an die Marke anpassen: login_enqueue_scripts, die Logo-Filter login_headerurl und login_headertext, login_message, generische Fehlermeldungen und die Entscheidung zwischen Must-use-Plugin und Child-Theme. Alle Hooks und Versionsangaben sind gegen den Quellcode von WordPress 7.1 geprüft. Für Härtung, die über das Aussehen hinausgeht, siehe unseren Leitfaden zur robusten Absicherung.
Was WordPress auf wp-login.php lädt
Bevor Sie das Logo austauschen, lohnt ein Blick darauf, was der Kern bei einer Anfrage an wp-login.php tut:
- Er lädt
wp-admin/css/login.cssund die abhängigen Dashboard-Stile (Buttons, Formulare). - Er löst
login_enqueue_scriptsaus. Hier binden Sie eigenes CSS und JS ein, genau wie mitwp_enqueue_scriptsim Frontend. - Er rendert den Kopf mit dem Logo-Link (standardmäßig auf wordpress.org), das Formular, die Links für vergessene Passwörter und Registrierung sowie die Fußzeile.
- Bei einem Validierungsfehler hängt er das Wackel-Skript an und zeigt die Meldung aus dem Filter
login_errors. - Die Filter
login_messageundlogin_messagessetzen HTML über das Formular (Hinweis nach dem Abmelden, Wartungshinweis, SSO-Banner).
Die wichtigste Folge: Die Login-Seite läuft nicht durch die Frontend-Pipeline des Themes. header.php, Vorlagen eines Block-Themes und die meisten Callbacks an wp_enqueue_scripts greifen dort nicht. Deshalb gibt es eine eigene Enqueue-Aktion, und deshalb brauchen die Login-Stile eine eigene Datei. Regeln, die nur in der style.css des Themes stehen, erreichen wp-login.php nie.
Die zweite Folge: Ein WordPress-Update kann Selektoren, die Reihenfolge der Skripte oder das Markup des Formulars ändern (zusätzliche Felder eines 2FA-Plugins zum Beispiel). Branding auf Basis von Hooks übersteht das Update, ein gepatchtes wp-login.php im Kern nicht.
Eigenes CSS für die WordPress-Login-Seite laden
Der graue Standardhintergrund (#f0f0f1 in der aktuellen login.css) passt selten zur Marke. Legen Sie eine Datei style-login.css im Theme an und laden Sie sie nur auf der Anmeldeseite, mit Versionsnummer, damit Browser nach einem Deploy nicht die alte Fassung aus dem Cache nehmen:
function wppoland_login_stylesheet() {
wp_enqueue_style(
'wppoland-login',
get_stylesheet_directory_uri() . '/style-login.css',
array(),
wp_get_theme()->get( 'Version' )
);
}
add_action( 'login_enqueue_scripts', 'wppoland_login_stylesheet' );Beispiel style-login.css:
body.login {
background-color: #0d1117;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.login form {
background: #161b22;
border: 1px solid #30363d;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
border-radius: 12px;
padding: 40px;
}
.login label {
color: #c9d1d9;
font-size: 14px;
font-weight: 500;
}
.login input[type="text"],
.login input[type="password"] {
background: #0d1117;
border: 1px solid #30363d;
border-radius: 6px;
color: #c9d1d9;
padding: 12px 16px;
font-size: 14px;
}
.login input[type="text"]:focus,
.login input[type="password"]:focus {
border-color: #58a6ff;
box-shadow: 0 0 0 3px rgba(88, 166, 255, 0.4);
}
.wp-core-ui .button-primary {
background: #238636;
border-color: rgba(27, 31, 35, 0.15);
border-radius: 6px;
padding: 12px 24px;
font-size: 14px;
font-weight: 600;
text-shadow: none;
box-shadow: none;
}
.wp-core-ui .button-primary:hover,
.wp-core-ui .button-primary:focus {
background: #2ea043;
}
.login #nav,
.login #backtoblog {
text-align: center;
}
.login #nav a,
.login #backtoblog a {
color: #8b949e;
}
.login #nav a:hover,
.login #backtoblog a:hover {
color: #58a6ff;
}Praktische Regeln für Login-CSS:
- Zielen Sie auf Klassen, die WordPress tatsächlich ausgibt:
body.login,#login,.login form,.wp-core-ui .button-primary,#login_error,.message. - Blenden Sie
#navund#backtoblognicht ohne Absprache mit dem Kunden aus. Redakteure verlieren sonst den Weg zurück zum Frontend, und die Passwort-Wiederherstellung wirkt kaputt. - Vermeiden Sie
display: noneauf Formularfeldern. Ein 2FA- oder Passkey-Plugin fügt eigene Felder hinzu, und per CSS versteckt sehen sie aus wie ein defektes Login. - Prüfen Sie den Kontrast (WCAG) bei Fehlermeldungen und Labels. Dunkler Hintergrund mit grauem Text fällt in Barrierefreiheits-Audits oft durch. Entfernen Sie den Fokusrahmen nicht ersatzlos: Im Beispiel oben übernimmt ein deutlich sichtbarer
box-shadowdiese Rolle.
Schriften des Kunden laden Sie hier oder hosten sie lokal im Theme. Eine dritte Domain auf dem Login-Bildschirm ist eine überflüssige Anfrage und ein weiterer DNS-Ausfallpunkt.
WordPress-Login-Logo ändern
WordPress hat keinen Filter, der die Logo-Datei austauscht. Das übliche Muster ist CSS auf #login h1 a als Hintergrundbild plus zwei Filter für die Attribute des Links.
function wppoland_login_logo() {
$logo = get_stylesheet_directory_uri() . '/images/kunden-logo.svg';
?>
<style type="text/css">
#login h1 a,
.login h1 a {
background-image: url(<?php echo esc_url( $logo ); ?>);
height: 65px;
width: 100%;
max-width: 320px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
padding-bottom: 30px;
}
@media (max-width: 768px) {
#login h1 a,
.login h1 a {
height: 50px;
max-width: 280px;
}
}
</style>
<?php
}
add_action( 'login_enqueue_scripts', 'wppoland_login_logo' );esc_url() auf dem Pfad ist Pflicht, auch wenn die URL aus get_stylesheet_directory_uri() stammt. Verwenden Sie SVG oder PNG mit Transparenz. Ein JPEG mit weißem Rand wirkt auf einem dunklen Formular wie ein Aufkleber. Die Media Query verkleinert das Logo auf schmalen Bildschirmen, damit es das Formular nicht nach unten drückt.
Der Standardlink des Logos führt zu wordpress.org. Leiten Sie ihn auf die Startseite um und setzen Sie den zugänglichen Linktext auf den Namen der Website:
function wppoland_login_logo_url() {
return home_url( '/' );
}
add_filter( 'login_headerurl', 'wppoland_login_logo_url' );
function wppoland_login_logo_url_title() {
return get_bloginfo( 'name' );
}
add_filter( 'login_headertext', 'wppoland_login_logo_url_title' );login_headertext ersetzt login_headertitle, das seit WordPress 5.2 als veraltet markiert ist. Ältere Snippets im Netz verwenden es noch.
Bei Installationen mit eigener Dashboard-Domain (cms.kunde.de neben www.kunde.de) zeigt home_url() weiter auf das öffentliche Frontend, was meist gewünscht ist. Soll das Logo zu einer internen Dokumentation oder zum Identity Provider führen, geben Sie eine vollständige HTTPS-URL zurück und testen Sie im privaten Fenster.
Meldung über dem WordPress-Login-Formular anzeigen
Der Filter login_message setzt HTML über das Formular. Typische Einsätze in Produktion:
- Ein Wartungshinweis („Login außerhalb des VPN heute Abend gesperrt“).
- Ein Hinweis für Redakteure („Bitte das Firmenkonto verwenden, kein privates“).
- Ein Banner nach dem Abmelden oder nach dem Zurücksetzen des Passworts (WordPress setzt dort auch eigene Meldungsklassen).
- Ein Link zum SSO, wenn der Identity Provider neben klassischen Passwörtern läuft.
/**
* Meldung über dem Login-Formular.
*
* @param string $message Vorhandenes HTML.
* @return string
*/
function wppoland_login_message( $message ) {
$notice = '<p class="message">' . esc_html__(
'Nur für Konten des Redaktionsteams. Verdacht auf ein geleaktes Passwort bitte an die IT melden.',
'wppoland'
) . '</p>';
return $notice . $message;
}
add_filter( 'login_message', 'wppoland_login_message' );Hinweise zur Umsetzung:
- Escapen Sie den Text (
esc_html__) oder bauen Sie das Markup mitwp_kses_post, wenn ein Link nötig ist. - Ersetzen Sie
$messagenicht blind. WordPress legt dort eigene Meldungen ab (nachloggedout=truezum Beispiel). Stellen Sie Ihren Text voran oder filtern Sie abhängig von der Anfrage. - Die Klasse
.messageist inlogin.cssbereits gestaltet. Ihrestyle-login.csssollte sie respektieren (Textfarbe, linker Rand), sonst verschwindet das Banner im Hintergrund.
Für Texte, die von der Aktion abhängen (login, lostpassword, rp), prüfen Sie $_GET['action'], statt denselben Hinweis bei der Passwort-Wiederherstellung und beim 2FA-Schritt zu zeigen.
Eigene Inhalte unter dem Login-Formular einfügen
Für einen Support-Hinweis unter dem Formular eignet sich die Aktion login_footer:
function wppoland_login_footer_content() {
?>
<div class="login-footer-content">
<p><?php echo esc_html__( 'Probleme bei der Anmeldung? Wenden Sie sich an den Support Ihrer Agentur.', 'wppoland' ); ?></p>
<p>© <?php echo esc_html( wp_date( 'Y' ) . ' ' . get_bloginfo( 'name' ) ); ?></p>
</div>
<?php
}
add_action( 'login_footer', 'wppoland_login_footer_content' );Die Gestaltung von .login-footer-content gehört in die style-login.css, nicht in einen eingebetteten <style>-Block. So bleiben alle Login-Regeln in einer Datei, die Sie versionieren.
Markenfarben des Kunden per CSS-Variablen setzen
Agenturen, die dieselbe Login-Vorlage für mehrere Kunden einsetzen, halten die Farben am besten als CSS-Variablen an einer Stelle:
function wppoland_agency_branding() {
$primary = sanitize_hex_color( '#0073aa' ); // Primärfarbe des Kunden
$secondary = sanitize_hex_color( '#005177' ); // Sekundärfarbe
?>
<style type="text/css">
:root {
--brand-primary: <?php echo esc_attr( $primary ); ?>;
--brand-secondary: <?php echo esc_attr( $secondary ); ?>;
}
body.login {
background: linear-gradient(135deg, var(--brand-primary) 0%, var(--brand-secondary) 100%);
}
.wp-core-ui .button-primary {
background: var(--brand-primary);
border-color: var(--brand-primary);
}
.wp-core-ui .button-primary:hover {
background: var(--brand-secondary);
border-color: var(--brand-secondary);
}
</style>
<?php
}
add_action( 'login_enqueue_scripts', 'wppoland_agency_branding' );Kommen die Farben später aus einer Option oder dem Customizer, sorgt sanitize_hex_color() (seit WordPress 3.4 in formatting.php, also auch auf der Login-Seite verfügbar) dafür, dass nur gültige Hex-Werte im CSS landen.
Login-Fehlermeldungen in WordPress verallgemeinern
Die Standardmeldung bei einem falschen Passwort kann verraten, dass ein Benutzer mit diesem Namen existiert. Das erleichtert die Enumeration von Konten vor einem Brute-Force-Angriff. Der Filter login_errors gibt stattdessen einen generischen Text zurück:
function wppoland_login_errors() {
return __( 'Anmeldung fehlgeschlagen. Bitte prüfen Sie Ihre Zugangsdaten.', 'wppoland' );
}
add_filter( 'login_errors', 'wppoland_login_errors' );Das erschwert die Aufklärung durch Angreifer. Es ist keine Firewall, kein Rate Limiting und kein 2FA. Sie brauchen weiterhin:
- Begrenzung der Anmeldeversuche auf Server, WAF oder mit einem gepflegten Plugin (mehr dazu im Leitfaden zum Login absichern),
- starke Passwörter und möglichst einen zweiten Faktor (TOTP-App, Hardware-Schlüssel),
- aktuelle Versionen von WordPress, Themes und Plugins,
- Zugriffsbeschränkung für
wp-adminund XML-RPC, wo die Firmenrichtlinie es erlaubt (VPN, IP-Allowlist, HTTP-Auth auf Staging).
In vielen Anleitungen tauchen eigene Login-Sperren per Transient auf login_init und Nonce-Prüfungen im Filter authenticate auf. Davon raten wir ab. login_init läuft bei jedem Aufruf von wp-login.php, also auch beim Zurücksetzen des Passworts, und ein wp_die() dort sperrt genau diesen Weg. Der Filter authenticate prüft auch Anmeldungen über XML-RPC, Anwendungspasswörter (wp_authenticate_application_password hängt laut default-filters.php mit Priorität 20 an diesem Filter) und wp_signon() aus Plugins wie WooCommerce, die kein solches Nonce-Feld mitsenden. Eine Nonce-Prüfung mit Priorität 30 bricht diese Anmeldewege.
Ebenso häufig: „Wir verstecken das Login, dann ist es sicher“. Warum das nicht trägt:
- Security through obscurity: Bots und Scanner kennen die Standardpfade. Eine geänderte URL ohne echte Zugriffskontrolle zerstört vor allem die Lesezeichen der Redakteure.
- CSS versteckt serverseitig nichts:
display: noneauf einem Login-Link im Menü entfernt den Endpunkt nicht.wp-login.phpundwp-adminantworten weiter. - Der Filter
login_urländert nur die Links, die WordPress erzeugt, nicht den Endpunkt selbst. Ein echter Umzug des Logins braucht Server-Konfiguration oder ein gepflegtes Plugin, und danach Tests für Passwort-Reset, WooCommerce „Mein Konto“, REST und Cron. - REST- und XML-RPC-Antworten können die Existenz von Benutzern unabhängig vom Branding des Bildschirms verraten.
Branding des Logins und Sicherheit sind zwei getrennte Spuren. White-Label verbessert UX und Vertrauen. Kontoschutz entsteht durch Berechtigungen, Rate Limits, 2FA und Updates.
Two-Factor-Felder auf der WordPress-Login-Seite gestalten
2FA selbst in der functions.php zu bauen ist das falsche Projekt. Nutzen Sie ein gepflegtes Plugin, zum Beispiel Two Factor aus dem WordPress.org-Verzeichnis (Version 0.17.0, laut Verzeichnis-API im Oktober 2026 über 100.000 aktive Installationen), und passen Sie dessen Felder an das Branding an.
Klassen, die dieses Plugin im zweiten Anmeldeschritt tatsächlich ausgibt (geprüft im Code der Version 0.17.0):
.two-factor-promptfür den Absatz mit der Anleitung,input.authcode(mitid="authcode") für den TOTP-Code, den E-Mail-Code und den Backup-Code; das Feld trägtinputmode="numeric"undautocomplete="one-time-code", überschreiben Sie diese Attribute also nicht per Skript, sonst schlägt das Telefon den Code aus SMS oder Passwortmanager nicht mehr vor,.backup-methods-wrapfür die Links zu alternativen Methoden,.two-factor-email-resendfür den Button, der den E-Mail-Code erneut sendet.
.login .two-factor-prompt {
color: #c9d1d9;
}
.login input.authcode {
background: #0d1117;
border: 1px solid #30363d;
color: #c9d1d9;
letter-spacing: 0.2em;
text-align: center;
}
.login .backup-methods-wrap a {
color: #c9d1d9;
}Selektoren wie .two-factor-methods oder .passkey-button, die in älteren Anleitungen kursieren, gibt es im aktuellen Plugin-Code nicht, und Regeln dafür greifen nie. Andere 2FA- und Passkey-Plugins haben eigenes Markup: Lesen Sie deren Selektoren im jeweiligen Code nach.
Wenn Administratoren ohne eingerichtetes 2FA nach dem Login direkt zur Einrichtung geschickt werden sollen, nutzen Sie den Filter login_redirect mit der öffentlichen Methode des Plugins:
function wppoland_2fa_setup_redirect( $redirect_to, $requested_redirect_to, $user ) {
if ( ! $user instanceof WP_User || ! class_exists( 'Two_Factor_Core' ) ) {
return $redirect_to;
}
if ( user_can( $user, 'manage_options' ) && ! Two_Factor_Core::is_user_using_two_factor( $user->ID ) ) {
return admin_url( 'profile.php#two-factor-options' );
}
return $redirect_to;
}
add_filter( 'login_redirect', 'wppoland_2fa_setup_redirect', 10, 3 );Two_Factor_Core::is_user_using_two_factor() und der Anker #two-factor-options im Profil stammen aus dem Plugin-Code. user_can() prüft den übergebenen Benutzer; current_user_can() wäre an dieser Stelle falsch, weil der aktuelle Benutzer während des Filters noch nicht gesetzt ist. Ein echter Zwang ist das nicht, nur ein Hinweis beim Login.
Shake-Effekt beim WordPress-Login entfernen
Wenn die Anmeldung fehlschlägt, wackelt das Formular. Manche Kunden finden das unprofessionell.
Das Snippet, das die meisten Anleitungen noch kopieren, remove_action( 'login_head', 'wp_shake_js', 12 ), bewirkt seit WordPress 5.4 nichts mehr. Der Kern hängt wp_shake_js inzwischen an login_footer, und zwar nur bedingt, innerhalb von login_header(). Das zeigt wp-login.php im Repository wordpress-develop; der Branch 5.3 nutzte noch login_head. Die stabile Methode ist der Filter shake_error_codes, verfügbar seit 3.0: Eine leere Liste von Fehlercodes bedeutet keine Animation.
add_filter( 'shake_error_codes', '__return_empty_array' );Der Filter ist öffentliche API und hängt weder von der Priorität noch davon ab, über welchen Hook der Kern das Skript gerade ausgibt.
Plugins für die WordPress-Login-Seite im Vergleich
Wer das Login nicht im Code pflegen will, findet im Verzeichnis auf WordPress.org mehrere Plugins. Stand laut Plugin-API von WordPress.org am 14. Oktober 2026:
| Plugin | Version | Aktive Installationen | Schwerpunkt |
|---|---|---|---|
| LoginPress | 6.2.5 | 200.000+ | Visueller Designer für wp-login.php |
| Custom Login Page Customizer | 2.5.4 | 90.000+ | Gestaltung im Customizer |
| Theme My Login | 7.3.1 | 50.000+ | Login-Seiten im Frontend |
Das früher oft genannte Plugin Login Designer ist im Verzeichnis inzwischen geschlossen und sollte nicht mehr neu installiert werden. Stapeln Sie kein Plugin auf die Hooks aus diesem Leitfaden: Zwei Quellen, die beide #login h1 a gestalten, überschreiben sich gegenseitig. Entscheiden Sie sich für Code oder ein Plugin.
Must-use-Plugin oder Child-Theme für den Login-Code
Wo soll der Code liegen? Es gibt zwei sinnvolle Orte und einen falschen.
Child-Theme (functions.php und style-login.css)
- Vorteile: Logo und Farben reisen mit dem Frontend-Design; der Designer ändert Dateien in einem Repository; Versionierung über
Versionin derstyle.css. - Nachteile: Ein Theme-Wechsel (Störung, A/B-Test, Umstieg auf ein Block-Theme) schaltet das Login-Branding ab. Auf Multisite mit unterschiedlichen Themes je Website muss der Code dupliziert oder nach oben verlagert werden, siehe unsere Multisite-Architektur.
Must-use-Plugin (wp-content/mu-plugins/wppoland-login-branding.php)
- Vorteile: Läuft unabhängig vom aktiven Theme, ideal für Agentur-Netzwerke und Installationen, deren Theme wechselt; schwer versehentlich im Dashboard zu deaktivieren.
- Nachteile: Assets (Logo, CSS) laden Sie aus dem Verzeichnis des Plugins (
plugin_dir_url( __FILE__ )); der Deploy von Must-use-Plugins fällt in Workflows, die nur das Theme ausrollen, gern unter den Tisch.
Der falsche Ort: Änderungen in wp-admin/ oder ein Patch an wp-login.php im Kern. Beides verschwindet beim nächsten Update. Meiden Sie auch Snippet-Plugins, die PHP ohne Versionskontrolle in der Datenbank speichern: Bei der Migration von Staging zu Produktion gehen die Snippets verloren oder werden doppelt angelegt.
<?php
/**
* Plugin Name: WPPoland Login Branding
* Description: White-Label für wp-login.php unabhängig vom Theme.
* Author: wppoland.com
*/
defined( 'ABSPATH' ) || exit;
add_action( 'login_enqueue_scripts', function () {
wp_enqueue_style(
'wppoland-login',
plugin_dir_url( __FILE__ ) . 'assets/style-login.css',
array(),
'2026.10.14'
);
} );
add_filter( 'login_headerurl', function () {
return home_url( '/' );
} );
add_filter( 'login_headertext', function () {
return get_bloginfo( 'name' );
} );Entscheidungsregel fürs Briefing: Ist das Login-Branding Teil des Kundenprodukts (Markenfarben, Kampagnenlogo), gehört es ins Child-Theme. Ist es ein Agenturstandard auf vielen Installationen (dasselbe Agenturlogo auf allen Staging-Umgebungen, generische Fehler, kein Wackeln), gehört es in ein Must-use-Plugin oder ein gemeinsames Composer-Paket, das auf alle Umgebungen ausgerollt wird.
Login-Seiten von WooCommerce und Mitgliedschafts-Plugins anpassen
Die Kontoseiten von WooCommerce und die Login-Blöcke im Checkout haben ein anderes Markup als wp-login.php. CSS für den Login-Bildschirm verändert die Formulare unter my-account nicht. Entweder bleiben die Standardformulare von Woo, oder Sie laden auf diesen Templates ein eigenes Stylesheet. Wer beides in style-login.css mischt, hinterlässt tote Regeln und verwirrt den nächsten Entwickler.
Dieselbe Trennung gilt für LearnDash, MemberPress und vergleichbare Produkte: Erst klären, über welche Adresse sich Kunden tatsächlich anmelden, dann genau diese Oberfläche gestalten. Ein typischer Agenturfehler ist ein polierter wp-login.php, während Kunden nur ein Modal im Frontend sehen, das in einem iframe weiterhin das WordPress-Logo zeigt.
Login-Seite nach WordPress-Core-Updates prüfen
Größere WordPress-Releases ändern gelegentlich das Login-Markup oder das Standard-CSS. Nach dem Core-Update auf Staging:
- Wenn etwas komisch aussieht, das Login-HTML mit der Version vor dem Update vergleichen.
- Logogröße erneut prüfen; neue Standardhöhen können SVGs abschneiden.
- Wenn Sie den Shake-Effekt deaktiviert haben, prüfen, ob der Filter
shake_error_codesweiterhin greift. - 2FA-Felder erneut testen, falls das Plugin im selben Zeitraum aktualisiert wurde.
Koppeln Sie die Version des Stylesheets an die Theme- oder Plugin-Version, damit Browser nach einer Kontrastkorrektur keine veraltete style-login.css behalten.
Welche Login-Hooks WordPress seit welcher Version bietet
Die Tabelle stammt aus den @since-Angaben in src/wp-login.php im Repository wordpress-develop (Oktober 2026, aktuelle Version WordPress 7.1.3). Sie hilft, wenn ein Kunde eine alte Installation betreibt oder ein Forum-Snippet einen Hook nutzt, den es noch nicht gibt oder der bereits veraltet ist.
| Hook | Typ | Seit | Zweck |
|---|---|---|---|
login_headerurl | Filter | 2.1.0 | URL des Logo-Links |
login_message | Filter | 2.1.0 | HTML über dem Formular |
login_errors | Filter | 2.1.0 | Fehlertext |
login_messages | Filter | 2.5.0 | Informationsmeldungen |
login_redirect | Filter | 3.0.0 | Weiterleitungsziel nach dem Login |
shake_error_codes | Filter | 3.0.0 | Fehlercodes, die das Formular wackeln lassen |
login_enqueue_scripts | Aktion | 3.1.0 | CSS und JS der Login-Seite |
login_footer | Aktion | 3.1.0 | Ausgabe in der Fußzeile |
login_init | Aktion | 3.2.0 | Beginn der Verarbeitung der Anfrage |
login_body_class | Filter | 3.5.0 | Klassen des body-Elements |
login_header | Aktion | 4.6.0 | Ausgabe direkt nach dem öffnenden body-Tag |
login_title | Filter | 4.9.0 | Inhalt des title-Tags |
login_link_separator | Filter | 4.9.0 | Trenner zwischen den Links unter dem Formular |
login_headertext | Filter | 5.2.0 | Linktext des Logos |
login_site_html_link | Filter | 5.7.0 | Link zurück zur Website in der Fußzeile |
login_display_language_dropdown | Filter | 5.9.0 | ob die Sprachauswahl erscheint |
login_language_dropdown_args | Filter | 5.9.0 | Argumente der Sprachliste |
login_headertitle (seit 2.1.0) ist seit 5.2.0 veraltet und läuft über apply_filters_deprecated. Mit aktivem WP_DEBUG hinterlässt er einen Hinweis im Log. Nutzt ein Kunden-Theme ihn noch, stellen Sie auf login_headertext um.
Titel, Body-Klasse und Sprachauswahl auf wp-login.php ändern
Vier Filter aus der Tabelle erledigen kleine Wünsche aus dem Briefing, ohne CSS anzufassen:
// Kürzerer Tab-Titel: Name des Bildschirms und Name der Website.
add_filter( 'login_title', function ( $login_title, $title ) {
return $title . ' | ' . get_bloginfo( 'name', 'display' );
}, 10, 2 );
// Eigene Klasse am body, damit Login-Regeln nicht mit anderen Stylesheets kollidieren.
add_filter( 'login_body_class', function ( $classes ) {
$classes[] = 'wppoland-login';
return $classes;
} );
// Der Link in der Fußzeile führt zur Hilfeseite statt zur Startseite.
add_filter( 'login_site_html_link', function () {
return sprintf(
'<a href="%s">%s</a>',
esc_url( home_url( '/hilfe/' ) ),
esc_html__( 'Hilfe für Redakteure', 'wppoland' )
);
} );
// Keine Sprachliste unter dem Formular.
add_filter( 'login_display_language_dropdown', '__return_false' );Details, die erst im Quellcode des Kerns sichtbar werden:
- Der Standardtitel setzt sich aus dem Namen des Bildschirms, dem Namen der Website und dem Wort WordPress am Ende zusammen. Im Wiederherstellungsmodus stellt der Kern ein Präfix voran, bevor er den Filter aufruft. Ein Callback, der den Titel nur aus
$titleneu baut, verliert dieses Präfix, und der Administrator sieht im Tab nicht mehr, dass die Website im Wiederherstellungsmodus läuft. Ist das wichtig, ändern Sie$login_title, statt ihn zu ersetzen. - Die Sprachliste erscheint nur, wenn mindestens ein zusätzliches Sprachpaket installiert ist, und nie im Fenster zur erneuten Anmeldung im Dashboard. Sie auszublenden ändert die Sprache des Kontos nicht: Nach dem Login gilt die Einstellung im Profil.
login_site_html_linkersetzt das ganze<a>-Element, das Escaping von URL und Text liegt also bei Ihnen.- Der Link zur Datenschutzerklärung unter dem Formular kommt aus
the_privacy_policy_link()und erscheint, sobald eine Datenschutzseite festgelegt ist. Blenden Sie ihn auf Websites, die über ein Registrierungsformular Daten erheben, nicht per CSS aus.
Welche Sicherheits-Header WordPress auf wp-login.php sendet
Bevor Sie eigene Header oder Meta-Tags für die Login-Seite ergänzen, prüfen Sie, was der Kern bereits tut. Laut default-filters.php und wp-login.php:
send_frame_options_header()anlogin_init(seit 3.1.3) sendetX-Frame-Options: SAMEORIGIN, und seit WordPress 6.9 ergänzt dieselbe FunktionContent-Security-Policy: frame-ancestors 'self'. Die Login-Seite lässt sich nicht auf einer fremden Domain in einen Frame einbetten.wp_admin_headers()anlogin_init(seit 4.9) sendetReferrer-Policy: strict-origin-when-cross-origin; der Filteradmin_referrer_policyändert den Wert.wp_robots_sensitive_page()(seit 5.7) ergänztnoindexundnoarchiveim Robots-Meta-Tag, daswp_robotsanlogin_headausgibt.wp_strict_cross_origin_referrer()(seit 5.7) ergänzt ein Referrer-Meta-Tag mit derselben Richtlinie.wp_site_iconanlogin_headgibt das Favicon aus der Einstellung Website-Icon aus.
In der Praxis verdoppelt ein eigenes Snippet, das ein Robots-Meta-Tag mit noindex oder einen Favicon-Link an login_head ausgibt, nur vorhandene Tags. X-XSS-Protection sollten Sie gar nicht setzen. MDN beschreibt den Header als nicht standardisiert und veraltet, warnt, dass er auf ansonsten sicheren Websites XSS-Lücken erzeugen kann, und empfiehlt Content-Security-Policy. Header für die gesamte Website (HSTS, CSP) gehören in die Server- oder CDN-Konfiguration, nicht in PHP an login_init, damit sie auch wp-admin und REST abdecken.
Angepasste WordPress-Login-Seite funktioniert nicht
CSS wird nicht angewendet
- Dateipfad der CSS-Datei überprüfen (Dateiname im Code und im Theme müssen übereinstimmen)
- Versionsnummer im Enqueue erhöhen oder Browser-Cache leeren
- Priorität der Hooks überprüfen
Logo wird nicht angezeigt
- Dateiberechtigungen überprüfen
- Bei SVG prüfen, ob der Server den MIME-Typ
image/svg+xmlsendet - Pfad mit
get_stylesheet_directory_uri()überprüfen
Umleitungsschleifen
- Alle Login-Plugins deaktivieren
- 2FA-Einstellungen überprüfen
- Callbacks an
login_redirectüberprüfen
Konflikte mit Sicherheits-Plugins
- Ein Plugin nach dem anderen testen
- Ladereihenfolge der Hooks überprüfen
- Plugin-Dokumentation konsultieren
Login-Branding auf Staging testen
Gehen Sie auf einer Kopie der Produktion der Reihe nach vor:
- CSS und Logo hochladen;
wp-login.phpohne Cache öffnen (privates Fenster). - Auf das Logo klicken: Sie landen auf dem Frontend des Kunden, nicht auf wordpress.org.
- Mit gültigem Konto anmelden, abmelden, mit falschem Passwort anmelden: Die Meldung ist generisch.
- Passwort-Wiederherstellung und Reset-Mail auf einer Umgebung mit eingerichtetem SMTP prüfen.
- Ist 2FA aktiv, den kompletten Ablauf einmal am Desktop und einmal am Telefon durchspielen.
- Vorübergehend auf ein Standard-Theme wechseln: Verschwindet das Branding, obwohl es global gelten sollte, gehört der Code in ein Must-use-Plugin.
- Dateipfade und Filterliste in der README des Projekts festhalten, damit der nächste Entwickler nicht in fünf Snippet-Plugins nach der Logik sucht.
Nach der Abnahme denselben Smoke-Test direkt nach dem Deploy auf Produktion wiederholen.
Zusammenfassung
Eine angepasste Anmeldeseite ist wenig Code mit großer Wirkung auf den Eindruck eines Projekts.
Wichtige Punkte:
- Branding: Logo, Link auf die Startseite, Linktext über
login_headertext - Styling: eigene, versionierte
style-login.cssüberlogin_enqueue_scripts - Sicherheit: generische Fehlermeldungen, 2FA für Administratoren, Versuchsbegrenzung auf Server oder WAF
- Wackeln:
shake_error_codesstatt des veraltetenremove_action - Ort: Child-Theme oder Must-use-Plugin, nie Kerndateien
Geben Sie dem Kunden eine einseitige Notiz mit: wo der Code liegt, wie das Logo getauscht wird und welche URL für Mitarbeiter-Logins gilt. Mehr über unsere WordPress-Sicherheitsaudits.







