Login überall

Nicht wenige WordPress-Nutzer wünschen sich die Möglichkeit sich auch z.B. auf der Startseite einloggen zu können anstatt erst die Login-Seite aufrufen zu müssen. WordPress trägt dem Rechnung und stellt die Funktion wp_login_form zur Verfügung. Für einfacher gelagerte Fälle keine schlechte Lösung, jedoch für etwas anspruchsvollere Geister nicht unbedingt das was sie suchen. Denn im Fehlerfall, z.B. bei einem falschen Passwort, landet man doch wieder auf der Login-Seite.
Schöner wäre es, würde der komplette Login-Prozess genau dort statt findet, wo das Login-Formular angezeigt wird. Wer sich nicht scheut ein Iframe zu benutzen, der kann folgende vergleichsweise einfache Lösung benutzen.

Login im Iframe

Im Grunde genommen kann man den ganzen Login-Prozess in einem Iframe ablaufen lassen. Man muss sich dabei lediglich vor Augen halten das ein Iframe mit einem neuen Tab im Browser vergleichbar ist. Dem Server ist es jedoch egal ob man den Login in einem neuen Tab oder Iframe vornimmt. Ob ein Benutzer eingeloggt ist oder nicht, wird in einem Cookie gespeichert. Dadurch ist der “Ort” wo man sich einloggt uninteressant, so lange er vom gleichen Server aus erfolgt.

Fangen wir also gleich damit an die wp-login.php in einem Iframe anzuzeigen. Damit dies ein wenig komfortabler wird, legen wir uns eine Funktion an die wir in der functions.php oder einem Plugin ablegen können.

function my_login_form( $args ){

	extract( $args );

	if( !isset( $width ) ){
		$width = 300;
	}

	if( !isset( $height ) ){
		$height = 300;
	}

	if( !isset( $redirect ) ){
		$redirect = content_url() . '/themes/my_theme/logout.php';
	}

	echo '<iframe src="http://www.example.com/wp-login.php?redirect_to=' . $redirect . '&iframe_mode=true" width="' . $width . '" height="' . $height . '">';
}

Diese Funktion macht eigentlich nichts anderes als ein Iframe anzuzeigen welches als Source die wp-login.php hat. Die Zeilen 3-16 dienen lediglich dazu ein paar Parameter an die Funktion zu übergeben. Im Beispiel oben sind das width (Breite des Iframe), height (Höhe des Iframe) und redirect_to (Ziel-URL zu der nach dem Login umgeleitet werden soll). Diese Parameter werden per Array übergeben:

if( function_exists('my_login_form') ){
	$args = array( 'width'=>300,
		       'height'=>200,
			redirect_to=> content_url().'/themes/my_theme/mylogin_redirect.php' );
	my_login_form( $args );
}

Fügen wir obigen Code-Schnipsel in unser Blog ein, z.B. in der Sidebar, dann fügt die Funktion an dieser Stelle ein Iframe mit der Breite 300px und Höhe 200px ein. Bis hierhin nichts wirklich aufregendes, einzig der Parameter redirect_to tanzt ein wenig aus der Reihe.
Wir erinnern uns, die Anzeige im Iframe ist mit einem neuen Tab vergleichbar. Die Situation ist nun folgende: Innerhalb des Blogs wird die wp-login.php angezeigt, beim Betätigen des  Submit-Buttons leitet die wp-login.php, sofern die Login-Daten korrekt sind, automatisch auf eine andere Seite um. Diese Seite wird dann ebenfalls im Iframe angezeigt! Normalerweise wird auf die Profil-Seite des Benutzers bzw. ins Dashboard umgelietet, in einem kleinen Iframe dargestellt sieht dies eher unbrauchbar aus. Diese Umleitung kann man jedoch beim Aufruf der wp-login.php mit dem Parameter redirect_to beeinflussen.
Dies machen wir uns zu nutzen und zeigen einfach eine eigene Seite an deren Inhalt besser in das Iframe passt. Diese Datei hat noch eine weitere recht wichtige Aufgabe. Denn durch den Aufruf von wp-login.php würden wir eine weitere Instanz von WordPress erzeugen was zu unschönen Nebeneffekten führen könnte. Ich habe hier als Beispiel mal den Benutzernamen und einen Logout-Link ausgegeben. Wichtig ist, dass das Script mit einem exit; beendet wird:

<?php
global $current_user;

echo $current_user->user_name . '<br />';
echo '<a href="' . wp_logout_url( site_url().'/wp-login.php' ) . '" title="Logout">' . __('Logout') . '</a>';
exit;
?>

Durch die Angabe von site_url . '/wp-login.php' wird beim Betätigen des Logout-Links (innerhalb des Iframes) wieder auf die Login-Seite umgeleitet.

Fehlende Optik

Damit haben wir uns bis jetzt ein schönes Karussell gebastelt.  Im Iframe wird die wp-login.php angezeigt, nach einem erfolgreichen Login wird unsere eigene Seite angezeigt und nach dem Ausloggen wieder die wp-login.php.
Jetzt bleibt noch ein kleines aber nicht unbedeutendes Problem übrig. Die wp-login.php würde im Iframe mit dem originalem Stylesheet angezeigt werden, dieses ist aber nicht auf Miniformate wie z.B. 300x200px ausgelegt. Zudem haben wir nun ein paar Elemente drin auf die wir gerne verzichten würden. Ein angepasstes Stylesheet muss also her. Wie man den Login-Screen optisch an seine eigenen Bedürfnisse anpasst, dazu finden sich im Internet massig Anleitungen. Zur Not einfach Bei Frank Bültge vorbei schauen, dort findet sich (fast) immer etwas passendes.
Ein kleines Problem gibt es dabei allerdings. Bei Verwendung des Hooks würde ein Benutzer der die wp-login.php “normal” aufrufen würde (z.B. über ein Bookmark), ebenfalls das angepasste Stylesheet zu sehen bekommen. Es muss also ein Kriterium her anhand dessen man unterscheiden kann ob die wp-login.php im Iframe oder in einem normalen Fenster angezeigt wird. Im Script selber können wir das (leider) nicht überprüfen, deswegen geben wir diese Information beim Aufruf der wp-login.php als GET-Parameter mit: &iframe_mode=true sorgt dafür das wir im Hook überprüfen können ob dieser Parameter gesetzt ist. Ist dem so, dann wird das angepasste Stylesheet geladen, ansonsten passiert nichts.

function check_iframe_mode(){

	if( isset( $_REQUEST['iframe_mode'] ) && true === $_REQUEST['iframe_mode'] ){
		echo '<style type="text/css">
		@import url("' . site_url().'/themes/my_theme/my_login_style.css");
		</style>';
	}

}

add_action( 'login_head', 'check_iframe_mode' );

Das Stylesheet liegt in diesen Beispiel im Themes-Ordner ‘my_theme’ und hat den Namen ‘my_login_style.css’. Man kann das CSS auch direkt ausgeben, jedoch lässt sich eine separate Datei leichter pflegen und anpassen.

Fazit

Mit diesem letzten Schritt wären wir nun am Ziel angekommen. Nun findet der Login-Prozess komplett im Iframe statt. Allerdings hat diese Methode auch ein paar Nachteile die ich hier nicht verschweigen möchte.
Zum einen wird keine Rücksicht auf die Seite genommen in der das Iframe eingebettet ist. Sind hier Elemente vorhanden die vom Login abhängig sind, z.B. Anzeige des Benutzernamens, dann werden diese Elemente erst dann sichtbar bzw. aktualisiert wenn die Seite erneut geladen wird. Diesen Mangel kann man zur Not noch mit etwas zusätzlichem JavaScript beheben indem man einen Reload der Hauptseite erzwingt.
Zum anderen geht diese Methode nicht sehr schonend mit den Resourcen um. Denn alleine durch die Anzeige der wp-login.php werden Datenbankverbindungen aufgebaut, Variablen angelegt und damit letztendlich auch Speicher verbraucht. Für Blogs mit hohen Besucheraufkommen sollte man deswegen besser auf andere Lösungen, sprich komplexere Plugins, zurück greifen.
Für kleinere Blogs und den Hobby-Bastler jedoch eine Anregung für einen weiteren Ausbau. Ein Workaround könnte so aussehen, dass man nach dem Logout nicht direkt wieder auf die wp-login.php umleitet, sondern auf eine dritte “Zwischenseite” die einen Link zur wp-login.php enthält.

Ich hoffe dem einen oder anderem mit diesem Artikel ein paar Anregungen gegeben zu haben und freue mich über etwas Feedback in den Kommentaren.