Sichern Sie eine Webanwendung im Java-Stil

Die Websicherheit kann je nach Sichtweise auf verschiedene Arten definiert werden. Das Hauptaugenmerk der Sicherheit in diesem Artikel liegt auf der Sicherheit von Anwendungen, die für das Internet entwickelt und bereitgestellt wurden. Hier werde ich einige Software-Sicherheitsmaßnahmen skizzieren, die Sie zur Sicherung Ihrer Anwendung ergreifen können. Obwohl keiner von ihnen völlig unfehlbar ist, kann die Kombination dieser Ansätze mit Hardware dazu beitragen, böswillige Angriffe auf Ihr Unternehmen zu verhindern.

Die beiden Hauptkonzepte der Sicherheit sind Authentifizierung und Autorisierung. Ich werde sie in den folgenden Abschnitten beschreiben und Beispiele dafür geben, wie Sie sie in Ihren Anwendungen implementieren können. Darüber hinaus werde ich einige Schlüsselklassen der Java-Sicherheits-API erläutern, um ein detaillierteres Beispiel vorzubereiten, das die formularbasierte Authentifizierung mit dem Sicherheitsmodell von Java kombiniert. Die im Beispiel beschriebenen Konzepte sollten es Ihrem Unternehmen ermöglichen, eine Sicherheitsrichtlinie für Ihre Java-basierten Anwendungen zu erstellen.

Authentifizierung

Bei der Authentifizierung werden die Zugriffsrechte der Benutzer überprüft, bevor sie den geschützten Bereich einer Website betreten. Es gibt zwei Hauptauthentifizierungsansätze: Basisauthentifizierung und formularbasierte Authentifizierung.

Grundlegende Authentifizierung

Die Standardauthentifizierung basiert auf dem Webserver für die Authentifizierung in geschützten Bereichen. Durch die Basisauthentifizierung geschützte Websites ermöglichen dem Benutzer das Durchsuchen ungeschützter Bereiche, ohne dass der Benutzer ein Kennwort eingeben muss. Der Browser fordert den Benutzer jedoch automatisch zur Eingabe eines Kennworts und eines Benutzernamens auf, falls er versucht, auf eine sichere Seite zuzugreifen. Diese Eingabeaufforderung wird in Form eines Dialogfelds angezeigt.

Die Kombination aus Benutzername und Passwort wird dann verschlüsselt (Basis 64) und unverschlüsselt an den Webserver übergeben. Der Webserver vergleicht den codierten Wert mit Werten, die in einer Einfachdatei, einer Datenbank oder einem Verzeichnisserver gespeichert sind.

Wenn der Benutzer authentifiziert ist, überprüft der Server, ob der Benutzer über die Berechtigung verfügt, über eine Datei wie httpd.conf auf die angeforderte Seite zuzugreifen. Wenn der Benutzer Zugriff hat, stellt der Webserver die Seite bereit. Wenn dem Benutzer der Zugriff verweigert wird, fordert der Server entweder die Kombination aus Benutzername und Kennwort erneut an oder zeigt eine Fehlermeldung im Browserfenster an.

Da die tatsächliche Syntax der Basisauthentifizierung zwischen den Servern variiert, werde ich hier keine präsentieren. Es gibt zahlreiche Webressourcen, die die Syntax der verschiedenen Server beschreiben.

Formularbasierte Authentifizierung

Die meisten Websites verwenden einen Ansatz, der als formularbasierte verzögerte Authentifizierung bezeichnet wird und es Benutzern ermöglicht, durch ungeschützte Bereiche der Website zu navigieren, ohne ein Kennwort zu benötigen. Nur wenn der Benutzer auf geschützte Bereiche wie Bestellung oder Kontostatus zugreifen möchte, wird auf der Website ein Anmeldeformular angezeigt. Dies ist der gängigste Sicherheitsansatz und wird von großen E-Commerce-Unternehmen wie Barnes & Noble verwendet. Der Vorteil dieses Ansatzes besteht darin, dass Benutzer nicht den mit der Authentifizierung verbundenen Wartezeiten ausgesetzt sind, es sei denn, sie benötigen wirklich Zugriff auf eine geschützte Seite.

Als das am häufigsten verwendete Sicherheitsschema im Web eignet sich die formularbasierte verzögerte Authentifizierung für das in diesem Artikel vorgestellte Beispiel.

Verwenden Sie Formulare, um Clients zu authentifizieren

Eine übliche Methode für servletbasierte Systeme zur Authentifizierung besteht darin, in der Sitzung Informationen zu speichern, die darauf hinweisen, dass sich ein Benutzer beim System angemeldet hat. In diesem Schema verwendet die Authentifizierungslogik das HttpSessionObjekt, das von der Servlet-Engine auf dem Webserver verwaltet wird.

In diesem Fall ist ein Basisservlet mit Kenntnissen der Authentifizierung hilfreich. Mit der serviceMethode von BaseServletkönnen die erweiterten Servlets die Sicherheitsüberprüfungsfunktion wiederverwenden. Der gesamte in diesem Beispiel verwendete Code befindet sich unter Ressourcen.

Die serviceMethode wird im folgenden Codeausschnitt gezeigt:

public void service (HttpServletRequest-Anforderung, HttpServletResponse-Antwort) löst IOException, ServletException aus {// prüfe, ob für diesen Benutzer bereits eine Sitzung erstellt wurde // erstelle keine neue Sitzung. HttpSession session = request.getSession (false); String requestPage = request.getParameter (Constants.REQUEST); if (session! = null) {// Authentifizierungsparameter aus der Sitzung abrufen Boolean isAuthenticated = (Boolean) session.getValue (Constants.AUTHENTICATION); // wenn der Benutzer nicht authentifiziert ist if (! isAuthenticated.booleanValue ()) {// die nicht authentifizierte Anfrage verarbeiten unauthenticatedUser (response, requestPage); }} else // die Sitzung existiert nicht {// daher ist der Benutzer nicht authentifiziert // verarbeitet die nicht authentifizierte Anfrage unauthenticatedUser (response, requestPage); }}

Beachten Sie, dass Sie diese Methode erweitern können, um auch andere generische Funktionen auszuführen. In diesem Beispiel habe ich nur die Sicherheitsaspekte dieser Klasse entwickelt.

Die BaseServletVersuche, die Sitzung von der Servlet-Engine abzurufen. Beim Abrufen überprüft das Servlet, ob dem Benutzer Zugriff auf das System gewährt wurde. Sollte eine dieser Prüfungen fehlschlagen, leitet das Servlet den Browser zum Anmeldebildschirm weiter.

Auf dem Anmeldebildschirm wird der Benutzer zur Eingabe eines Benutzernamens und eines Kennworts aufgefordert. Beachten Sie, dass die vom Browser an den Webserver übergebenen Daten unverschlüsselt sind, es sei denn, Sie verwenden SSL (Secure Socket Layer).

Der LoginServletverwendet die Kombination aus Benutzername und Kennwort, um die Datenbank abzufragen und sicherzustellen, dass dieser Benutzer tatsächlich Zugriff auf das System hat. Wenn die Prüfung keinen Datensatz für diesen Benutzer zurückgibt, wird der Anmeldebildschirm erneut angezeigt. Wenn die Prüfung erfolgreich ist, speichert der folgende Code die Benutzerauthentifizierungsinformationen in einer Sitzungsvariablen.

// erstelle eine Sitzung session = request.getSession (true); // konvertiere den Booleschen Wert in einen Booleschen Wert Boolescher Wert booleanIsAuthenticated = new Boolean (isAuthenticated); // speichere den booleschen Wert in der Sitzung session.putValue (Constants.AUTHENTICATION, booleanIsAuthenticated);

In diesem Beispiel wird davon ausgegangen, dass jeder Benutzer, der sich erfolgreich beim System authentifiziert, Zugriff auf die vor der Anmeldung angezeigten Seiten hat. Es gibt jedoch Fälle, in denen das Anwendungsentwicklungsteam möglicherweise einen verfeinerten Sicherheitsansatz benötigt, um seine Anforderungen zu erfüllen.

Genehmigung

Durch die Autorisierung wird überprüft, ob die Sicherheitsrichtlinien vor anspruchsvolleren Hackern schützen, indem verhindert wird, dass nicht autorisierter Code eine Verbindung zu Back-Office-Systemen wie Enterprise JavaBeans (EJB) herstellt. Es gibt zwei Arten der Autorisierung: Code-Autorisierung und Anrufer-Autorisierung.

Code-Autorisierung

Ihr Sicherheitsteam kann die Verwendung von nicht autorisiertem Code verhindern, indem es die Klassen einschränkt, die für die von der Servlet-Engine verwendete virtuelle Maschine verfügbar sind. Sie können diesen Prozess der Code-Autorisierung erreichen, indem Sie unnötige Einträge aus dem Klassenpfad entfernen.

Das Sicherheitsteam hat die vollständige Kontrolle darüber, welcher Code in den Klassenpfad aufgenommen werden soll, und kann den Code daher vor dem Einfügen autorisieren. Das Team sollte sicherstellen, dass der Code keinen Zugriff auf Tools von Drittanbietern oder fremden Code hat.

Anruferautorisierung

Neben der Code-Autorisierung können Sie auch den Anrufer von Back-Office-Systemen authentifizieren. Mit dem EJB-Modell kann das Entwicklungsteam beispielsweise einen Benutzernamen und ein Kennwort für den Zugriff auf eine in einem Container bereitgestellte Bean angeben.

Jeder Code, der versucht, eine Verbindung zu diesen Beans herzustellen, muss die Kombination aus Benutzername und Kennwort zur Autorisierung an den Container übergeben. Eine fehlgeschlagene Autorisierung führt zu einer Ausnahme, die den Anrufer daran hindert, seine Aktion abzuschließen.

Autorisierungsbeispiel

In diesem zweiten Beispiel werde ich die in die EJB-Spezifikation integrierten Mechanismen untersuchen, um den unbefugten Zugriff auf die Geschäftslogik zu verhindern. Während dieses Beispiel auf dem WebLogic Tengah-Server basiert, gelten die Konzepte für andere Server, obwohl sich die Syntax unterscheidet. Informationen zu den in diesem Beispiel verwendeten Code- oder Konfigurationsdateien finden Sie unter Ressourcen.

Im Deployment-Deskriptor der EJB identifiziert der folgende Code die mit der Bean verknüpften Zugriffssteuerungseinträge:

(accessControlEntries DEFAULT [Administratoren basicUsers] theRestrictedMethod [Administratoren]); end accessControlEntries

Beachten Sie, dass zwei Benutzerkategorien identifiziert wurden. Administratoren haben standardmäßig Zugriff auf die Bean und bilden die einzige Benutzergruppe, auf die Zugriff besteht theRestrictedMethod.

Nachdem Sie autorisiert haben, dass die Administratoren Zugriff auf die Bean haben, müssen Sie jetzt Eigenschaften erstellen, in denen angegeben ist, welche Benutzer zur Administratorgruppe gehören. Dazu muss die Datei weblogic.properties die folgenden Zeilen enthalten:

weblogic.password.JoeAdministrator = joe weblogic.security.group.administrators = JoeAdministrator weblogic.password.JaneBasic = jane weblogic.security.group.basicUsers = JaneBasic 

Zu diesem Zeitpunkt haben Sie die Benutzer eingerichtet, die Zugriff auf die Bean haben und bestimmte spezifische Methoden eingeschränkt haben. Dies hilft, das Potenzial für böswillige Angriffe auf Ihren Webserver zu begrenzen, um die in den Beans gespeicherte Geschäftslogik zu erreichen.

Der letzte Schritt in diesem EJB-Autorisierungsbeispiel besteht darin, die Clientverbindung zur Bean herzustellen. In diesem Fall muss der Client die Kombination aus Benutzername und Kennwort korrekt angeben, um Zugriff auf die eingeschränkte Bean oder die eingeschränkten Methoden zu erhalten. Es folgt eine beispielhafte Client-Kommunikation:

try {Properties myProperties = new Properties (); myProperties.put (Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.T3InitialContextFactory"); myProperties.put (Context.PROVIDER_URL, "t3: // localhost: 7001"); myProperties.put (Context.SECURITY_PRINCIPAL, "JoeAdministrator"); myProperties .put (Context.SECURITY_CREDENTIALS, "joe"); ic = neuer InitialContext (myProperties); ...} catch (Ausnahme e) {...}

Since you've passed the JoeAdministrator user to the InitialContext, you'll have access to any method to which the administrators group has been granted access. If your application makes connections to external beans or your beans are used by external applications, you should implement this security authorization.

Java security

In the Java Security API, there is a package, java.security.acl, that contains several classes that you can use to establish a security system in Java. These classes enable your development team to specify different access capabilities for users and user groups. All code used in this example can be found in Resources.

The concept is fairly straightforward. A user or user group is granted permission to functionality by adding that user or group to an access control list. For example, consider a java.security.Principal called testUser as shown below:

Principal testUser = new PrincipalImpl ("testUser"); 

Now you can create a Permission object to represent the capability of reading from a file.

Permission fileRead = new PermissionImpl ("readFile"); 

Once you have created the user and the user's permission, you can create the access control list entry. It's important to note that the security APIs require that the owner of the access list be passed in order to ensure that this is truly the developer's desired action. It is essential that this owner object be protected carefully.

Acl accessList = new AclImpl (Eigentümer, "exampleAcl"); 

In der endgültigen Form enthält die Zugriffsliste eine Reihe von Zugriffslisteneinträgen. Sie können diese wie folgt erstellen:

AclEntry aclEntry = new AclEntryImpl (testUser); aclEntry.addPermission (fileRead); accessList.addEntry (Eigentümer, aclEntry);

In den vorhergehenden Zeilen wird ein neues AclEntryObjekt für erstellt testUser, die fileReadBerechtigung zu diesem Eintrag hinzugefügt und der Eintrag dann zur Zugriffssteuerungsliste hinzugefügt.

Sie können die Benutzerberechtigungen jetzt ganz einfach wie folgt überprüfen:

boolean isReadFileAuthorized = accessList.checkPermission (testUser, readFile);