JavaRush /Java-Blog /Random-DE /JAAS – Einführung in die Technologie (Teil 1)
Viacheslav
Level 3

JAAS – Einführung in die Technologie (Teil 1)

Veröffentlicht in der Gruppe Random-DE
Zugriffssicherheit ist in Java schon seit geraumer Zeit implementiert und die Architektur zur Bereitstellung dieser Sicherheit heißt JAAS – Java Authentication and Authorization Service. In dieser Rezension wird versucht, das Geheimnis zu lüften, was Authentifizierung und Autorisierung ist und was JAAS damit zu tun hat. Wie JAAS mit der Servlet-API befreundet ist und wo es Probleme in ihrer Beziehung gibt.
JAAS – Einführung in die Technologie (Teil 1) – 1

Einführung

In dieser Rezension möchte ich ein Thema wie die Sicherheit von Webanwendungen diskutieren. Java verfügt über mehrere Technologien, die Sicherheit bieten: Aber unser heutiges Gespräch wird sich um eine andere Technologie drehen, die „Java Authentication and Authorization Service (JAAS)“ heißt. Sie ist es, die so wichtige Dinge wie Authentifizierung und Autorisierung beschreibt. Schauen wir uns das genauer an.
JAAS – Einführung in die Technologie (Teil 1) – 2

JAAS

JAAS ist eine Erweiterung von Java SE und wird im Java Authentication and Authorization Service (JAAS) Reference Guide beschrieben . Wie der Name der Technologie vermuten lässt, beschreibt JAAS, wie Authentifizierung und Autorisierung durchgeführt werden sollten:
  • Authentifizierung “: Aus dem Griechischen übersetzt bedeutet „authentikos“ „echt, echt“. Das heißt, die Authentifizierung ist ein Authentizitätstest. Dass derjenige, der authentifiziert wird, wirklich der ist, für den er sich ausgibt.

  • Autorisierung “: aus dem Englischen übersetzt bedeutet „Erlaubnis“. Das heißt, bei der Autorisierung handelt es sich um eine Zugriffskontrolle, die nach erfolgreicher Authentifizierung durchgeführt wird.

Das heißt, bei JAAS geht es darum, festzustellen, wer Zugriff auf eine Ressource anfordert, und zu entscheiden, ob er diesen Zugriff erhalten kann. Eine kleine Analogie aus dem Leben: Sie fahren die Straße entlang und ein Kontrolleur hält Sie an. Bitte legen Sie Dokumente vor – Authentifizierung. Darf man mit Papieren ein Auto fahren – Genehmigung. Oder Sie möchten beispielsweise in einem Geschäft Alkohol kaufen. Zunächst werden Sie um einen Reisepass gebeten – eine Authentifizierung. Anschließend wird anhand Ihres Alters entschieden, ob Sie zum Kauf von Alkohol berechtigt sind. Das ist Autorisierung. In Webanwendungen ist die Anmeldung als Benutzer (Eingabe eines Benutzernamens und eines Passworts) eine Authentifizierung. Und welche Seiten Sie öffnen können, hängt von der Autorisierung ab. Hier hilft uns „Der Java Authentication and Authorization Service (JAAS)“. Bei der Betrachtung von JAAS ist es wichtig, mehrere Schlüsselkonzepte zu verstehen, die JAAS beschreibt: Betreff, Auftraggeber, Anmeldeinformationen. Betreff ist der Betreff der Authentifizierung. Das heißt, es ist der Inhaber oder Inhaber von Rechten. In der Dokumentation wird „Betreff“ als Quelle einer Anforderung zur Ausführung einer Aktion definiert. Das Thema oder die Quelle muss irgendwie beschrieben werden und zu diesem Zweck wird Principal verwendet, das im Russischen manchmal auch Principal genannt wird. Das heißt, jeder Prinzipal ist eine Darstellung eines Subjekts aus einer bestimmten Sicht. Um es klarer zu machen, geben wir ein Beispiel: Eine bestimmte Person ist ein Subjekt. Als Auftraggeber können folgende Personen fungieren:
  • seinen Führerschein als Darstellung einer Person als Verkehrsteilnehmer
  • seinen Reisepass als Repräsentation einer Person als Staatsbürger ihres Landes
  • sein ausländischer Pass, als Repräsentation einer Person als Teilnehmer an internationalen Beziehungen
  • seinen Bibliotheksausweis in der Bibliothek, als Repräsentation einer Person als mit der Bibliothek verbundener Leser
Darüber hinaus verfügt der Betreff über eine Reihe von „Credential“, was auf Englisch „Identität“ bedeutet. Auf diese Weise bestätigt das Subjekt, dass es es ist. Beispielsweise kann das Passwort des Benutzers der Berechtigungsnachweis sein. Oder irgendein Gegenstand, mit dem der Benutzer bestätigen kann, dass er wirklich er selbst ist. Sehen wir uns nun an, wie JAAS in Webanwendungen verwendet wird.
JAAS – Einführung in die Technologie (Teil 1) – 3

Internetanwendung

Wir brauchen also eine Webanwendung. Das automatische Projekterstellungssystem Gradle wird uns bei der Erstellung helfen. Dank der Verwendung von Gradle können wir durch die Ausführung kleiner Befehle ein Java-Projekt in dem von uns benötigten Format zusammenstellen, automatisch die erforderliche Verzeichnisstruktur erstellen und vieles mehr. Weitere Informationen zu Gradle finden Sie in der Kurzübersicht: „ Eine kurze Einführung in Gradle “ oder in der offiziellen Dokumentation „ Gradle Getting Started “. Wir müssen das Projekt initialisieren (Initialisierung), und zu diesem Zweck verfügt Gradle über ein spezielles Plugin: „ Gradle Init Plugin “ (Init ist die Abkürzung für Initialization, leicht zu merken). Um dieses Plugin zu verwenden, führen Sie den Befehl in der Befehlszeile aus:
gradle init --type java-application
Nach erfolgreichem Abschluss werden wir ein Java-Projekt haben. Öffnen wir nun das Build-Skript unseres Projekts zur Bearbeitung. Ein Build-Skript ist eine Datei namens build.gradle, die die Nuancen des Anwendungsbuilds beschreibt. Daher der Name Build-Skript. Wir können sagen, dass dies ein Projekterstellungsskript ist. Gradle ist ein so vielseitiges Tool, dessen Grundfunktionen durch Plugins erweitert werden. Achten wir daher zunächst auf den Block „Plugins“:
plugins {
    id 'java'
    id 'application'
}
Standardmäßig hat Gradle gemäß unseren Angaben „ --type java-application“ eine Reihe einiger Kern-Plugins eingerichtet, d. h. der Plugins, die in der Distribution von Gradle selbst enthalten sind. Wenn Sie auf der Website gradle.org zum Abschnitt „Dokumente“ (d. h. Dokumentation) gehen, sehen wir links in der Themenliste im Abschnitt „Referenz“ den Abschnitt „ Kern-Plugins “, d. h. Abschnitt mit einer Beschreibung dieser sehr einfachen Plugins. Wählen wir genau die Plugins aus, die wir benötigen, und nicht die, die Gradle für uns generiert hat. Der Dokumentation zufolge stellt das „ Gradle Java Plugin “ grundlegende Operationen mit Java-Code bereit, beispielsweise das Kompilieren von Quellcode. Außerdem stellt uns das „ Gradle-Anwendungs-Plugin “ laut Dokumentation Tools für die Arbeit mit der „ausführbaren JVM-Anwendung“ zur Verfügung, d.h. mit einer Java-Anwendung, die als eigenständige Anwendung gestartet werden kann (z. B. eine Konsolenanwendung oder eine Anwendung mit eigener Benutzeroberfläche). Es stellt sich heraus, dass wir das „Anwendungs“-Plugin nicht brauchen, weil... Wir brauchen keine eigenständige App, wir brauchen eine Web-App. Lass es uns löschen. Sowie die Einstellung „mainClassName“, die nur diesem Plugin bekannt ist. Darüber hinaus gibt es im selben Abschnitt „ Verpackung und Vertrieb “, in dem der Link zur Anwendungs-Plugin-Dokumentation bereitgestellt wurde, einen Link zum Gradle War-Plugin. Das Gradle War Plugin bietet, wie in der Dokumentation angegeben, Unterstützung für die Erstellung von Java-Webanwendungen im War-Format. Im WAR-Format bedeutet, dass anstelle eines JAR-Archivs ein WAR-Archiv erstellt wird. Es scheint, dass wir das brauchen. Außerdem heißt es in der Dokumentation: „Das War-Plugin erweitert das Java-Plugin“. Das heißt, wir können das Java-Plugin durch das War-Plugin ersetzen. Daher wird unser Plugin-Block letztendlich so aussehen:
plugins {
    id 'war'
}
Auch in der Dokumentation zum „Gradle War Plugin“ heißt es, dass das Plugin ein zusätzliches „Project Layout“ verwendet. Layout wird aus dem Englischen als Standort übersetzt. Das heißt, das War-Plugin erwartet standardmäßig die Existenz eines bestimmten Speicherorts für Dateien, die es für seine Aufgaben verwenden wird. Es verwendet das folgende Verzeichnis zum Speichern von Webanwendungsdateien: src/main/webapp Das Verhalten des Plugins wird wie folgt beschrieben:
JAAS – Einführung in die Technologie (Teil 1) – 4
Das heißt, das Plugin berücksichtigt Dateien von diesem Speicherort beim Erstellen des WAR-Archivs unserer Webanwendung. Darüber hinaus heißt es in der Dokumentation zum Gradle War Plugin, dass dieses Verzeichnis das „Stammverzeichnis des Archivs“ sein wird. Und bereits darin können wir ein WEB-INF-Verzeichnis erstellen und dort die Datei web.xml hinzufügen. Was ist das für eine Datei? web.xml- Dies ist ein „Deployment Descriptor“ oder „Deployment Descriptor“. Dies ist eine Datei, die beschreibt, wie wir unsere Webanwendung so konfigurieren, dass sie funktioniert. Diese Datei gibt an, welche Anfragen unsere Anwendung verarbeiten wird, welche Sicherheitseinstellungen es gibt und vieles mehr. Im Kern ähnelt es einer Manifestdatei aus einer JAR-Datei (siehe „ Arbeiten mit Manifestdateien: Die Grundlagen “). Die Manifest-Datei erklärt, wie mit einer Java-Anwendung (d. h. einem JAR-Archiv) gearbeitet wird, und die web.xml erklärt, wie man mit einer Java-Webanwendung (d. h. einem WAR-Archiv) arbeitet. Das eigentliche Konzept des „Deployment Descriptor“ ist nicht eigenständig entstanden, sondern wird im Dokument „ Servlet API Specification“ beschrieben.". Jede Java-Webanwendung hängt von dieser „Servlet-API“ ab. Es ist wichtig zu verstehen, dass es sich um eine API handelt, das heißt, es handelt sich um eine Beschreibung eines Interaktionsvertrags. Webanwendungen sind keine unabhängigen Anwendungen. Sie werden auf einem Webserver ausgeführt , das die Netzwerkkommunikation mit Benutzern ermöglicht. Das heißt, ein Webserver ist eine Art „Container“ für Webanwendungen. Das ist logisch, weil wir die Logik einer Webanwendung schreiben wollen, d. h. welche Seiten der Benutzer wie sehen wird Sie sollten auf die Aktionen des Benutzers reagieren. Und wir möchten keinen Code dafür schreiben, wie eine Nachricht an den Benutzer gesendet wird, wie Informationsbytes übertragen werden und andere Dinge auf niedriger Ebene und mit sehr hohen Qualitätsanforderungen. Darüber hinaus Es stellt sich heraus, dass Webanwendungen alle unterschiedlich sind, die Datenübertragung jedoch gleich ist. Das heißt, eine Million Programmierer müssten immer wieder Code für denselben Zweck schreiben. Der Webserver ist also für einen Teil der Benutzerinteraktion verantwortlich und Datenaustausch, und die Webanwendung und der Entwickler sind für die Generierung dieser Daten verantwortlich. Und um diese beiden Teile zu verbinden, d.h. Webserver und Webanwendung benötigen Sie für deren Zusammenspiel einen Vertrag, d.h. Welche Regeln werden sie dabei befolgen? Um den Vertrag irgendwie zu beschreiben, wie die Interaktion zwischen einer Webanwendung und einem Webserver aussehen sollte, wurde die Servlet-API erfunden. Interessanterweise läuft unter der Haube auch dann noch eine Servlet-API, wenn Sie Frameworks wie Spring verwenden. Das heißt, Sie verwenden Spring und Spring arbeitet für Sie mit der Servlet-API. Es stellt sich heraus, dass unser Webanwendungsprojekt von der Servlet-API abhängig sein muss. In diesem Fall ist die Servlet-API eine Abhängigkeit. Wie wir wissen, können Sie mit Gradle auch Projektabhängigkeiten deklarativ beschreiben. Plugins beschreiben, wie Abhängigkeiten verwaltet werden können. Beispielsweise führt das Java Gradle Plugin eine Abhängigkeitsverwaltungsmethode „testImplementation“ ein, die besagt, dass eine solche Abhängigkeit nur für Tests erforderlich ist. Aber das Gradle War Plugin fügt eine Abhängigkeitsverwaltungsmethode „providedCompile“ hinzu, die besagt, dass eine solche Abhängigkeit nicht in das WAR-Archiv unserer Webanwendung aufgenommen wird. Warum nehmen wir die Servlet-API nicht in unser WAR-Archiv auf? Denn die Servlet-API wird unserer Webanwendung vom Webserver selbst bereitgestellt. Wenn ein Webserver eine Servlet-API bereitstellt, wird der Server als Servlet-Container bezeichnet. Daher liegt es in der Verantwortung des Webservers, uns die Servlet-API bereitzustellen, und es liegt in unserer Verantwortung, die Servlet-API nur zum Zeitpunkt der Kompilierung des Codes bereitzustellen. Deshalb providedCompile. Somit sieht der Abhängigkeitsblock folgendermaßen aus:
dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testImplementation 'junit:junit:4.12'
}
Kehren wir also zur Datei web.xml zurück. Standardmäßig erstellt Gradle keinen Bereitstellungsdeskriptor, daher müssen wir dies selbst tun. Lassen Sie uns ein Verzeichnis erstellen src/main/webapp/WEB-INFund darin eine XML-Datei namens erstellen web.xml. Öffnen wir nun die „Java Servlet Specification“ selbst und das Kapitel „ KAPITEL 14 Deployment Descriptor “. Wie in „14.3 Bereitstellungsdeskriptor“ angegeben, wird das XML-Dokument des Bereitstellungsdeskriptors durch das Schema http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd beschrieben . Ein XML-Schema beschreibt, aus welchen Elementen ein Dokument bestehen kann und in welcher Reihenfolge sie erscheinen sollen. Welche sind obligatorisch und welche nicht. Im Allgemeinen beschreibt es die Struktur des Dokuments und ermöglicht die Überprüfung, ob das XML-Dokument korrekt zusammengesetzt ist. Nutzen wir nun das Beispiel aus dem Kapitel „ 14.5 Beispiele “, allerdings muss das Schema für Version 3.1 angegeben werden, d.h.
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd
Unser leeres web.xmlwird so aussehen:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <display-name>JAAS Example</display-name>
</web-app>
Beschreiben wir nun das Servlet, das wir mit JAAS schützen werden. Zuvor hat Gradle die App-Klasse für uns generiert. Machen wir daraus ein Servlet. In der Spezifikation in „ KAPITEL 2 Die Servlet-Schnittstelle “ heißt es: „ Für die meisten Zwecke erweitern Entwickler HttpServlet, um ihre Servlets zu implementieren “, das heißt, um eine Klasse zu einem Servlet zu machen, müssen Sie diese Klasse erben von HttpServlet:
public class App extends HttpServlet {
	public String getGreeting() {
        return "Secret!";
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().print(getGreeting());
    }
}
Wie bereits erwähnt, ist die Servlet-API ein Vertrag zwischen dem Server und unserer Webanwendung. Mit diesem Vertrag können wir beschreiben, dass, wenn ein Benutzer den Server kontaktiert, der Server eine Anfrage des Benutzers in Form eines Objekts generiert HttpServletRequestund diese an das Servlet weiterleitet. Außerdem wird dem Servlet ein Objekt bereitgestellt HttpServletResponse, damit das Servlet eine Antwort für den Benutzer darauf schreiben kann. Sobald die Ausführung des Servlets abgeschlossen ist, kann der Server dem Benutzer eine darauf basierende Antwort bereitstellen HttpServletResponse. Das heißt, das Servlet kommuniziert nicht direkt mit dem Benutzer, sondern nur mit dem Server. Damit der Server weiß, dass wir ein Servlet haben und für welche Anfragen es verwendet werden muss, müssen wir dem Server dies im Bereitstellungsdeskriptor mitteilen:
<servlet>
	<servlet-name>app</servlet-name>
	<servlet-class>jaas.App</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>app</servlet-name>
	<url-pattern>/secret</url-pattern>
</servlet-mapping>
In diesem Fall /secretwerden nicht alle Anfragen namentlich an unser einziges Servlet gerichtet app, das der Klasse entspricht jaas.App. Wie bereits erwähnt, kann eine Webanwendung nur auf einem Webserver bereitgestellt werden. Der Webserver kann separat (Standalone) installiert werden. Für die Zwecke dieser Überprüfung ist jedoch eine alternative Option geeignet – die Ausführung auf einem eingebetteten Server. Das bedeutet, dass der Server programmgesteuert erstellt und gestartet wird (das Plugin erledigt dies für uns) und gleichzeitig unsere Webanwendung darauf bereitgestellt wird. Das Gradle-Build-System ermöglicht Ihnen die Verwendung des Plugins „ Gradle Gretty Plugin “ für folgende Zwecke:
plugins {
    id 'war'
    id 'org.gretty' version '2.2.0'
}
Darüber hinaus verfügt das Gretty-Plugin über eine gute Dokumentation . Beginnen wir mit der Tatsache, dass Sie mit dem Gretty-Plugin zwischen verschiedenen Webservern wechseln können. Dies wird in der Dokumentation „ Wechsel zwischen Servlet-Containern “ ausführlicher beschrieben . Wechseln wir zu Tomcat, weil... Es ist eines der am häufigsten verwendeten und verfügt außerdem über eine gute Dokumentation sowie viele Beispiele und analysierte Probleme:
gretty {
    // Переключаемся с дефолтного Jetty на Tomcat
    servletContainer = 'tomcat8'
    // Укажем Context Path, он же Context Root
    contextPath = '/jaas'
}
Jetzt können wir „gradle appRun“ ausführen und dann ist unsere Webanwendung unter http://localhost:8080/jaas/secret verfügbar
JAAS – Einführung in die Technologie (Teil 1) – 5
Es ist wichtig zu überprüfen, ob der Servlet-Container von Tomcat ausgewählt wird (siehe Nr. 1) und zu überprüfen, unter welcher Adresse unsere Webanwendung verfügbar ist (siehe Nr. 2).
JAAS – Einführung in die Technologie (Teil 1) – 6

Authentifizierung

Authentifizierungseinstellungen bestehen häufig aus zwei Teilen: Einstellungen auf der Serverseite und Einstellungen auf der Seite der Webanwendung, die auf diesem Server ausgeführt wird. Die Sicherheitseinstellungen einer Webanwendung müssen mit den Sicherheitseinstellungen des Webservers interagieren, es sei denn, eine Webanwendung kann aus keinem anderen Grund mit dem Webserver interagieren. Nicht umsonst sind wir auf Tomcat umgestiegen, denn... Tomcat verfügt über eine gut beschriebene Architektur (siehe „ Apache Tomcat 8-Architektur “). Aus der Beschreibung dieser Architektur wird deutlich, dass Tomcat als Webserver die Webanwendung als einen bestimmten Kontext darstellt, der als „ Tomcat-Kontext “ bezeichnet wird. Dieser Kontext ermöglicht es jeder Webanwendung, ihre eigenen Einstellungen zu haben, die von anderen Webanwendungen isoliert sind. Darüber hinaus kann die Webanwendung die Einstellungen dieses Kontexts beeinflussen. Flexibel und bequem. Für ein tieferes Verständnis empfehlen wir die Lektüre des Artikels „ Understanding Tomcat Context Containers “ und des Tomcat-Dokumentationsabschnitts „ The Context Container “. Wie oben erwähnt, kann unsere Webanwendung den Tomcat-Kontext unserer Anwendung mithilfe einer /META-INF/context.xml. Und eine der sehr wichtigen Einstellungen, die wir beeinflussen können, sind Security Realms. Security Realms ist eine Art „Sicherheitsbereich“. Ein Bereich, für den bestimmte Sicherheitseinstellungen festgelegt sind. Dementsprechend wenden wir bei Verwendung eines Security Realms die für diesen Realm definierten Sicherheitseinstellungen an. Security Realms werden von einem Container verwaltet, d.h. Webserver, nicht unsere Webanwendung. Wir können dem Server nur mitteilen, welcher Sicherheitsbereich auf unsere Anwendung erweitert werden muss. Die Tomcat-Dokumentation im Abschnitt „ Die Realm-Komponente “ beschreibt einen Realm als eine Sammlung von Daten über Benutzer und ihre Rollen zur Durchführung der Authentifizierung. Tomcat bietet eine Reihe verschiedener Security Realm-Implementierungen, darunter das „ Jaas Realm “. Nachdem wir ein wenig die Terminologie verstanden haben, beschreiben wir den Tomcat-Kontext in der Datei /META-INF/context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Realm className="org.apache.catalina.realm.JAASRealm"
           appName="JaasLogin"
           userClassNames="jaas.login.UserPrincipal"
           roleClassNames="jaas.login.RolePrincipal"
           configFile="jaas.config" />
</Context>
appName- Anwendungsname. Tomcat wird versuchen, diesen Namen mit den in der Datei angegebenen Namen abzugleichen configFile. configFile- Dies ist die „Login-Konfigurationsdatei“. Ein Beispiel hierfür finden Sie in der JAAS-Dokumentation: „ Anhang B: Beispiel-Anmeldekonfigurationen “. Darüber hinaus ist es wichtig, dass diese Datei zuerst in den Ressourcen durchsucht wird. Daher kann unsere Webanwendung diese Datei selbst bereitstellen. Attribute userClassNamesund roleClassNamesenthalten einen Hinweis auf die Klassen, die den Prinzipal des Benutzers darstellen. JAAS trennt die Konzepte „Benutzer“ und „Rolle“ als zwei unterschiedliche Konzepte java.security.Principal. Beschreiben wir die oben genannten Klassen. Erstellen wir die einfachste Implementierung für den Benutzerprinzipal:
public class UserPrincipal implements Principal {
    private String name;
    public UserPrincipal(String name) {
        this.name = name;
    }
    @Override
    public String getName() {
        return name;
    }
}
Wir werden genau die gleiche Implementierung für wiederholen RolePrincipal. Wie Sie der Benutzeroberfläche entnehmen können, besteht die Hauptaufgabe von Principal darin, einen Namen (oder eine ID) zu speichern und zurückzugeben, der den Principal repräsentiert. Jetzt haben wir einen Sicherheitsbereich, wir haben Hauptklassen. Es bleibt noch, die Datei mit dem Attribut „“ zu füllen configFile, auch bekannt als login configuration file. Die Beschreibung finden Sie in der Tomcat-Dokumentation: „ The Realm Component “.
JAAS – Einführung in die Technologie (Teil 1) – 7
Das heißt, wir können die Einstellung JAAS Login Config in den Ressourcen unserer Webanwendung platzieren und dank Tomcat Context können wir sie verwenden. Diese Datei muss als Ressource für ClassLoader verfügbar sein, daher sollte ihr Pfad wie folgt aussehen: \src\main\resources\jaas.config Legen wir den Inhalt dieser Datei fest:
JaasLogin {
    jaas.login.JaasLoginModule required debug=true;
};
Es ist erwähnenswert, dass context.xmlhier und in derselbe Name verwendet wird. Dadurch wird der Sicherheitsbereich dem LoginModule zugeordnet. Tomcat Context hat uns also mitgeteilt, welche Klassen die Prinzipale darstellen und welches LoginModule verwendet werden soll. Wir müssen lediglich dieses LoginModule implementieren. LoginModule ist vielleicht eines der interessantesten Dinge in JAAS. Die offizielle Dokumentation hilft uns bei der Entwicklung von LoginModule: „ Java Authentication and Authorization Service (JAAS): LoginModule Developer's Guide “. Lassen Sie uns das Anmeldemodul implementieren. Erstellen wir eine Klasse, die die Schnittstelle implementiert LoginModule:
public class JaasLoginModule implements LoginModule {
}
Zuerst beschreiben wir die Initialisierungsmethode LoginModule:
private CallbackHandler handler;
private Subject subject;
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler, <String, ?> sharedState, Map<String, ?> options) {
	handler = callbackHandler;
	this.subject = subject;
}
Diese Methode speichert Subject, die wir weiter authentifizieren und mit Informationen über die Auftraggeber füllen. Darüber hinaus bewahren wir die CallbackHandleruns überlassenen Daten für eine spätere Verwendung auf. Mit Hilfe CallbackHandlerkönnen wir etwas später verschiedene Informationen zum Authentifizierungsgegenstand anfordern. Mehr dazu können Sie CallbackHandlerim entsprechenden Abschnitt der Dokumentation lesen: „ JAAS Reference Guide: CallbackHandler “. Als nächstes wird die Methode loginzur Authentifizierung ausgeführt Subject. Dies ist die erste Phase der Authentifizierung:
@Override
public boolean login() throws LoginException {
	// Добавляем колбэки
	Callback[] callbacks = new Callback[2];
	callbacks[0] = new NameCallback("login");
	callbacks[1] = new PasswordCallback("password", true);
	// При помощи колбэков получаем через CallbackHandler логин и пароль
	try {
		handler.handle(callbacks);
		String name = ((NameCallback) callbacks[0]).getName();
		String password = String.valueOf(((PasswordCallback) callbacks[1]).getPassword());
		// Далее выполняем валидацию.
		// Тут просто для примера проверяем определённые значения
		if (name != null && name.equals("user123") && password != null && password.equals("pass123")) {
			// Сохраняем информацию, которая будет использована в методе commit
			// Не "пачкаем" Subject, т.к. не факт, что commit выполнится
			// Для примера проставим группы вручную, "хардCodeно".
			login = name;
			userGroups = new ArrayList<String>();
			userGroups.add("admin");
			return true;
		} else {
			throw new LoginException("Authentication failed");
		}
	} catch (IOException | UnsupportedCallbackException e) {
		throw new LoginException(e.getMessage());
	}
}
Es ist wichtig, dass loginwir das nicht ändern Subject. Solche Änderungen sollten nur in der Bestätigungsmethode auftreten commit. Als nächstes müssen wir die Methode zur Bestätigung einer erfolgreichen Authentifizierung beschreiben:
@Override
public boolean commit() throws LoginException {
	userPrincipal = new UserPrincipal(login);
	subject.getPrincipals().add(userPrincipal);
	if (userGroups != null && userGroups.size() > 0) {
		for (String groupName : userGroups) {
			rolePrincipal = new RolePrincipal(groupName);
			subject.getPrincipals().add(rolePrincipal);
		}
	}
	return true;
}
Es mag seltsam erscheinen, die Methode loginund zu trennen commit. Der Punkt ist jedoch, dass Anmeldemodule kombiniert werden können. Und für eine erfolgreiche Authentifizierung kann es erforderlich sein, dass mehrere Login-Module erfolgreich funktionieren. Und erst wenn alle notwendigen Module funktioniert haben, speichern Sie die Änderungen. Dies ist die zweite Phase der Authentifizierung. Lassen Sie uns mit den abortund- Methoden abschließen logout:
@Override
public boolean abort() throws LoginException {
	return false;
}
@Override
public boolean logout() throws LoginException {
	subject.getPrincipals().remove(userPrincipal);
	subject.getPrincipals().remove(rolePrincipal);
	return true;
}
Die Methode abortwird aufgerufen, wenn die erste Phase der Authentifizierung fehlschlägt. Die Methode logoutwird aufgerufen, wenn sich das System abmeldet. Nachdem wir unseres implementiert Login Moduleund konfiguriert haben Security Realm, müssen wir nun angeben, web.xmldass wir ein bestimmtes verwenden möchten Login Config:
<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>JaasLogin</realm-name>
</login-config>
Wir haben den Namen unseres Sicherheitsbereichs und die Authentifizierungsmethode BASIC angegeben. Dies ist eine der Authentifizierungsarten, die in der Servlet-API im Abschnitt „ 13.6 Authentifizierung “ beschrieben werden. Blieb n
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION