HTML-Anmeldeformulare mit Apache Modul mod_auth_form
Apache stellt verschiedene Varianten für die Authentifizierung von Nutzern bereit. Die bekannteste ist wohl AuthType Basic die im Browser eine schnöde Eingabeaufforderung für Benutzername und Passwort erzeugt. Aber der Apache Webserver liefert mit mod_auth_form auch ein Modul mit, mit dem sich ein HTML-Formular für die Anmeldung nutzen und vor allem selbst adaptieren und gestalten lässt.
Module laden
Damit mod_auth_form funktioniert, muss das entsprechende Modul durch Auskommentieren in der httpd.conf geladen werden. Außerdem werden noch weitere Module zum Verarbeiten der Requests und zum Erzeugen und Speichern der Sessions benötigt.
LoadModule auth_form_module modules/mod_auth_form.so
LoadModule session_module modules/mod_session.so
LoadModule request_module modules/mod_request.so
LoadModule session_cookie_module modules/mod_session_cookie.so
LoadModule session_crypto_module modules/mod_session_crypto.so
vHosts konfigurieren
Die Konfiguration der vHosts muss entsprechend angepasst werden und unterscheidet sich ein wenig, je nachdem ob es sich um ein reales Verzeichnis oder eine Proxy-Konfiguration handelt.
Das Template für das HTML-Formular liegt in meinem Beispiel in einem eigenen Verzeichnis, dass mittels Alias alias.static.apache angesprochen werden kann. Auch eine manuelle Logout-Funktion lässt sich über ein virtuelles Verzeichnis logout und das Session-Handling realisieren.
Konfiguration für ein Verzeichnis
<Directory "/srv/www/admin">
Options FollowSymlinks
AllowOverride AuthConfig Indexes
AuthType form
AuthFormUsername bw_username
AuthFormPassword bw_password
ErrorDocument 401 /alias.static.apache/authform/login.htm
AuthName "Authentication required"
AuthFormProvider file
AuthUserFile /srv/htpasswd/admin.htpasswd
Session On
SessionCryptoPassphrase gUxw1NQnqCbkj01Ubv2E
SessionCookieName session path=/
SessionMaxAge 0
Require valid-user
</Directory>
<Location "/logout">
SetHandler form-logout-handler
AuthFormLogoutLocation "/"
Session on
SessionCryptoPassphrase gUxw1NQnqCbkj01Ubv2E
SessionCookieName session path=/
SessionMaxAge 1
</Location>
Konfiguration für einen Proxy
ProxyPreserveHost On
ProxyPass /alias.static.apache/ !
ProxyPass /logout !
ProxyPass / http://backendserver:8420/
ProxyPassReverse / http://backendserver:8420/
<Location />
AuthType form
AuthFormUsername bw_username
AuthFormPassword bw_password
ErrorDocument 401 /alias.static.apache/authform/login.htm
AuthName "Authentication required"
AuthFormProvider file
AuthUserFile /serv/htpasswd/backend.htpasswd
Session On
SessionCryptoPassphrase gUxw1NQnqCbkj01Ubv2E
SessionCookieName session path=/
SessionMaxAge 86400
<RequireAny>
Require valid-user
</RequireAny>
</Location>
<Location "/alias.static.apache">
Require all granted
</Location>
<Location "/logout">
SetHandler form-logout-handler
AuthFormLogoutLocation "/"
Session on
SessionCryptoPassphrase gUxw1NQnqCbkj01Ubv2E
SessionCookieName session path=/
SessionMaxAge 1
</Location>
Manchmal kann die durch den Proxy bereitgestellte Anwendung, nach der Umstellung auf mod_auth_form, nicht geladen werden (Browser lädt endlos). Dann sorgt die zusätzliche Direktive AuthFormLoginSuccessLocation / für Abhilfe.
HTML-Formular
Das HTML-Formular kann frei gestaltet werden, insofern die Feldbezeichnungen aus der Konfiguration für Benutzername und Passwort beachtet bzw. entsprechend adaptiert werden.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Authentication required</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<meta name="robots" content="noindex, nofollow" />
<link rel="shortcut icon" href="/alias.static.apache/authform/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" type="text/css" href="/alias.static.apache/authform/style.css" />
<script language="javascript" src="/alias.static.apache/authform/jquery/jquery-3.1.0.min.js" type="text/javascript"></script>
<script language="javascript" src="/alias.static.apache/authform/script.js" type="text/javascript"></script>
</head>
<body>
<h1>Authentication required to access <span class="bw_domain">the requested website</span></h1>
<form method="post" action="">
<div id="bw_error">
<p>Login failed!<br/>Please check the provided username and password and try again.</p>
</div>
<fieldset>
<label>Username</label>
<input type="text" name="bw_username" value="" id="bw_username" />
<label>Password</label>
<input type="password" name="bw_password" value="" id="bw_password" />
<input type="submit" value="Login" name="bw_login" />
</fieldset>
</form>
</body>
</html>
Das eingebundene JavaScript kümmert sich, um das Vorausfüllen des Benutzernamens und die Anzeige von Fehlermeldungen, denn das beherscht mod_auth_form leider noch nicht.
jQuery(document).ready(function(){
// write domain name in header
jQuery("span.bw_domain").text(window.location.hostname);
// invalidate locale storage items after 5 seconds
d = new Date();
limit = d.getTime() - 1000 * 5;
if(localStorage.getItem("bw_login") && localStorage.getItem("bw_login") < limit) {
localStorage.removeItem("bw_username");
localStorage.removeItem("bw_login");
}
// error handling and preserved values
if(localStorage.getItem("bw_login")){
jQuery("#bw_error").show();
}
if(localStorage.getItem("bw_username") && localStorage.getItem("bw_username").length > 0){
jQuery("#bw_username").val(localStorage.getItem("bw_username"));
jQuery("#bw_password").focus();
} else {
jQuery("#bw_username").focus();
}
// store data on login
jQuery("form").submit(function(){
localStorage.setItem("bw_username", jQuery("#bw_username").val());
d = new Date();
localStorage.setItem("bw_login", d.getTime());
});
// remove data after usage
localStorage.removeItem("bw_username");
localStorage.removeItem("bw_login");
});