Hallo zusammen
Derzeit bin ich mit den Admin-Seiten einer Webanwendung beschäftigt, die auf einem Tomcat-Server läuft. Diese Seiten soll hinterher ein Normalsterblicher bedienen können.
Natürlich sollen die Admin-Seiten auch passwortgeschützt sein, wobei ich das Passwort zur Laufzeit noch ändern können möchte. Dazu zählt aber ein gesamter Ordner, zu dem auch Bilder usw. gehören. Die Lösungen, die ich bei meiner Recherche gefunden habe, beziehen sich alle auf 2 Verfahren:
bei dem einen prüft jede JSP-Seite aufs Neue, ob der Benutzer autorisiert ist
→ Haken: Bilder und Textdateien können so nicht geschützt werden (kein JSP)
bei dem anderen wird die web.xml angepasst
→ Haken: Webanwendung muss nach jedem Ändern des Passwortes neu gestartet werden
Ideal wäre natürlich, wenn die Lösung auch ohne aktivierte Cookies funktioniert, mir würde ein Workaround mit Cookies aber schon reichen.
Habt ihr da eine Idee?
in einer zivilisierten Webanwendung (also anderes als PHP usw. ) sollte jeder Request, auch für Bilder und sonstiges,
über ein Servlet (oder je nach Framework hoffentlich vorhandene vergleichbare Java-Komponente) laufen,
mit Benutzer-Prüfung, Cookies und allem anderen
siehe z.B.
der Image-Pfad entweder als Parameter eines normalen Servlet-Namens mit normalen Mapping,
oder normale Image-URLs auf das ImageServlet umleiten, bestimmt etwas schwieriger in web.xml & Co.
*** Edit ***
[quote=Mythenmetz]* bei dem anderen wird die web.xml angepasst
→ Haken: Webanwendung muss nach jedem Ändern des Passwortes neu gestartet werden[/quote]
wie sieht denn der Interesse halber diese Lösung aus? Änderung der URLs?
Danke schonmal für die schnelle Antwort
Ja, die Idee, alle Requests auf ein Servlet umzuleiten, hatte ich auch schon. Bisher fand ich das mit JSPs so angenehm, dass ich exakt die Verzeichnisstruktur sehe, wie der Anwender auch, sodass ich mich um das Aushändigen der einzelnen Dateien nicht kümmern muss. Außerdem haben Servlets den entscheidenden Nachteil, dass Tomcat (bitte korrigiert mich) die Servlet-Anwendung nur dann akzeptiert, wenn ich die Anwendung als .war über die Manager-App hochlade (oder lokal mit dem Server bekannt mache).
Problem: Eigentlich stellt mir nur jemand seinen Server zur Verfügung, um mein Projekt drauf laufen zu lassen. Der Workflow sieht also prinzipiell so aus: Ich verändere meine Webanwendung, packe die neue Version in eine .war, und der Host lädt sie dann für mich hoch. Weil das bei einem Produktivsystem ziemlich nervig werden kann (ich kann nicht direkt eingreifen, wenn irgendwas nicht funktioniert), hab ich mir eine Reihe von Servlets programmiert, um wenigstens eine Art FTP-Ersatz zu haben. Ich kann mittlerweile also selbstständig Dateien hochladen. Zugriff auf die Manager-App hab ich dennoch nicht.
Deshalb versuche ich derzeit (so ungünstig das auch ist), möglichst viel Code in die JSPs zu schreiben, sodass ich meine Anwendungen auch „schnell mal verändern“ kann. Mir ist durchaus bewusst, dass so eine Anwendung nicht wirklich effizient und erst recht nicht objektorientiert entwickelt werden kann, allerdings hab ich derzeit keinen besseren Ansatz gefunden, die Situation zu umgehen. (Vorschläge sind hier sehr willkommen) Daher hab ich den Thread auch mit „JSP“ getaggt.
Mal nur so als Frage: Man liest überall, wie ärgerlich es wäre, Java-Code in JSP-Dateien zu schreiben, man solle lieber Java-Code in Servlets auslagern. Dazu gibt es ja auch genug Tags, mit denen man um Java-Code drum herum kommt, wenn man sich bemüht. Nur warum ist Java-Code in JSPs so ungerne gesehen? Ja, OOP ist da nicht so einfach, aber ansonsten?
Die web.xml-„Lösung“ sieht prinzipiell wie Folgt aus: Dem tomcat-users.xml füg ich einen neuen User hinzu. Innerhalb eines Security Constraints in der web.xml definiere ich dann den geschützten Bereich und kann dann über ein „login-config“-Tag die Authentifizierungsmethode angeben. Praktisch sieht das dann z.B. so aus:
Auf die Gefahr hin, dass dir das sonnenklar ist: Separation of Concerns. In die Darstellung gehört keine Anwendungslogik. Das verstreut die Anwendungslogik unnötigerweise in weit entfernt liegende Programmbestandteile, macht Wiederverwendung von Programmcode unmöglich (zumindest von dem, der direkt in der JSP steht) und birgt die Gefahr, dass durch die entstehenden Redundanzen bei einer Anpassung der Programmlogik nicht überall die notwendigen Anpassungen gemacht werden.
Dass eine andere Schnittstelle (z. B. ein REST-Interface) dadurch zur Qual wird, ist ein weiterer Nachteil.
Hm, schon. Aber ob ich jetzt <c:out value="${meinevariable}" />
oder <%= meinevariable %>" />
schreibe, ist doch eigentlich exakt das gleiche? Und dennoch steht auf diversen Webseiten, dass man letzteres besser vermeiden sollte.
Anders gefragt: Welchen Vorteil hat JSTL gegenüber Scriptlets?
Aber ich drifte vom Thema ab
Ich meinte natürlich <%= meinevariable %> Und das ist doch keine Anwendungslogik, oder? Und JSTL ist doch auch Anwendungslogik?
Hat ansonsten keiner eine Idee zur Lösung meines Problems? Ich brauche ja nur eine Antwort auf eine der beiden Fragen, der Rest würde sich dann ja ergeben:
Wie kann ich Tomcat-Users zur Laufzeit verändern, ohne den Server neu starten zu müssen? (ohne Servlet wäre ideal, mit Servlet ginge aber auch)
Wie kann ich ein Servlet zur Laufzeit verändern, ohne den Server neu starten zu müssen, wenn ich keinen Zugang zur Manager-App-GUI habe?
Nein, das ist Darstellungslogik. Ist natürlich auch eine gewisse Definitionsfrage, aber Anwendungslogik ist der Bestandteil, der einzig und allein dazu dient, das Problem zu lösen, für das die Anwendung entwickelt wurde.
Die Schnittstelle zum Menschen (ob CLI, GUI, Webinterface mit JSP oder was auch immer) ist (bzw. sollte) ein separater Baustein der Anwendung.
Wenn du in den Darstellungsteil nun Anwendungslogik packst, dann kann diese Trennung nicht vorhanden sein.
Der von dir geschilderte Fall ist noch keiner, in dem Anwendungslogik im Template steht. Die Gefahr ist aber, dass aus dieser einfachen Ausgabe ganz schnell mehr wird. Und da es eine abstrahierte Variante zur Ausgabe gibt, ist diese der „eingebetteten Java-Variante“ vorzuziehen.
Zum Deployment: Apache Tomcat 8 (8.0.53) - Tomcat Web Application Deployment
Ggf. könntest du mit Schreibberechtigungen ins „appBase“-Verzeichnis eine Anwendung deployen, wenn autoDeploy aktiviert ist. Wahrscheinlich hast du aber nicht die passenden Berechtigungen für das Verzeichnis.
Falls du die Berechtigungen doch hast und undeployOldVersions aktiviert ist, könntest du wie hier beschrieben ein Update der Webanwendung machen.
Die Variante mit der tomcat-users.xml ist eine supereinfache Implementierung eines sog. „Realms“. Du musst diesen gegen einen anderen Realm austauschen, der die Userdaten nicht cached, sondern IMMER aus dem Store (File, Datenbank o.ä.) holt. Nähere Infos zu Realms unter Tomcat gibt es hier: Apache Tomcat 7 (7.0.109) - Realm Configuration HOW-TO
Garnicht. Plain Servlets lassen sich nicht on the fly reloaden. Nur durch Reload/Restart des Contextes werden die Klassen neu geladen. Abhilfe schaffen hier evtl. Webframeworks, die ein dynamisches Neuladen ihrer Klassen unterstützen (Tapestry und Wicket machen das galube ich bspw.).
Vielen Dank zusammen! Das waren genau die Infos, die ich gesucht habe.
Wie schon gesagt, der einzige Zugriff auf den Server läuft über selbstgeschriebene JSP, so könnte ich quasi auf den gesamten Server zugreifen, ob ich das darf, ist eine andere Frage. Ich bitte den Host jetzt einfach mal, autoDeploy zu aktivieren, dann kann ich per JSP auch war-Dateien hochladen. Das ist natürlich ideal.
Und eine andere Implementierung eines Realms sollte mir mit der verlinkten Beschreibung auch gut gelingen.
Wobei ich noch eine kleine Frage an @nillehammer habe:
Hat cmrudolph nicht eine Möglichkeit des Reloads on the Fly vorgestellt? Oder gibt es da einen Haken?
Das ist kein Reload des aktuellen Deployments, sondern eine vollkommen neue Webanwendung, auf welche über den selben Kontextpfad zugegriffen wird wie auf die alte. Tomcat undeployed die alte Anwendung automatisch, sobald es keine offenen Sessions zu dieser mehr gibt.
Nagut, das ist in meinem Anwendungsfall vielleicht sogar ganz gut. Kann ich einzelne Dateien “behalten”, z.B. einen Log, oder muss ich den auf einen anderen Speicherort auslagern?
Die müssen in einem separaten Verzeichnis liegen, also nicht im Verzeichnis der entpackten War-Datei. Denn jede Version bekommt ein eigenes Verzeichnis (##). Wenn du nach $CATALINA_BASE/logs loggst, dann ist das natürlich kein Problem.
Perfekt, dann mache ich mich mal an die Programmierung, mal schauen, ob das dann so gut läuft, wie ihr das hier in der Theorie erklärt habt.
Schonmal ein ganz großes Dankeschön für eure Hilfsbereitschaft hier! Die hat mir auch schon bevor ich einen Account gehabt habe, als “stillem Mitleser”, sehr geholfen.