Vorwort HTTP ist ein zustandsloses Kommunikationsprotokoll. Die einzelnen Anfragen sind unabhängig voneinander und der Server kann vorherige Anfragen nicht identifizieren. Bei Webanwendungen sind alle Aktivitäten von einem bestimmten Status abhängig, beispielsweise von der Benutzeranmeldung. Zurzeit erfordert die Verwendung von HTTP die Möglichkeit, nach einer Anmeldeanforderung Anmeldeinformationen für nachfolgende Anfragen bereitzustellen. Dieser Artikel wurde zuerst auf dem öffentlichen Konto Dunwu Source Code veröffentlicht. Die Lösung besteht in der Verwendung von Cookies, die vom Server an den Browser zurückgegeben werden, der die Cookie-Daten zwischenspeichert und bei jeder Anforderung an den Server übermittelt. Cookies werden in Anfragen im Klartext übertragen und sind auf eine Größe von 4 KB begrenzt. Offensichtlich ist es unzuverlässig, alle Statusdaten im Browser zu speichern. Der gängige Ansatz ist:
Zur Vereinfachung der Verwaltung bezeichnet der Server den gesamten Prozess als Sitzung und abstrahiert ihn in eine Sitzungsklasse, die zum Identifizieren und Speichern von Informationen oder Statusinformationen über den Benutzer verwendet wird. 1. Lösen Sie die Sitzungskennung auf Cookies sind der am häufigsten verwendete Mechanismus zur Sitzungsverfolgung. Alle Servlet-Container, einschließlich Tomcat, unterstützen sie. In Tomcat lautet der Standardname des Cookies, das die Sitzungskennung speichert, JSESSIONID. Wenn Ihr Browser keine Cookies unterstützt, können Sie zur Erfassung von Kennungen auch folgende Methode verwenden:
Tomcat implementiert die Extraktion von JSESSIONID aus dem URL-Umschreibungspfad und Cookie. Bevor wir den Quellcode analysieren, schauen wir uns zunächst die wichtigsten Informationen der Header-Felder der Antwort zum Setzen von Cookies und der Anfrage mit Cookies an: // Cookie setzen HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Set-Cookie: JSESSIONID=56AE5B92C272EA4F5E0FBFEFE6936C91; Pfad=/Beispiele Datum: So, 12. Mai 2019 01:40:35 GMT // Cookie absenden GET /Beispiele/Servlets/Servlet/SessionExample HTTP/1.1 Host: localhost:8080 Kekse: JSESSIONID=56AE5B92C272EA4F5E0FBFEFE6936C91 1.1 Pfade aus URLs umschreiben Eine URL, die einen Sitzungs-ID-Pfadparameter enthält, sieht wie folgt aus:
Einfach ausgedrückt geht es darum, die JSESSIONID zwischen dem passenden Semikolon und dem letzten Schrägstrich zu finden, was tatsächlich der Fall ist, außer dass Tomcat mit Bytes arbeitet. Der Kerncode befindet sich in der Methode CoyoteAdapter.parsePathParameters(), die hier nicht veröffentlicht wird. 1.2 Aus dem Cookie-Header Der Methodenaufruf, der die Cookie-Analyse auslöst, lautet wie folgt: CoyoteAdapter.service(Anfrage, Antwort) └─CoyoteAdapter.postParseRequest(Anfrage, Anfrage, Antwort, Antwort) └─CoyoteAdapter.parseSessionCookiesId(Anfrage, Anfrage) └─Cookies.getCookieCount() └─Cookies.processCookies(MimeHeaders) └─Cookies.processCookieHeader(byte[], int, int) Dieser processCookieHeader arbeitet mit Bytes und die Analyse scheint nicht intuitiv. Es gibt auch eine Methode, die in Tomcat als veraltet markiert ist und die Zeichenfolgenanalyse verwendet, um sie leichter verständlich zu machen. Der Code lautet wie folgt: private void processCookieHeader(String cookieString){ // Mehrere Cookie-Werte werden durch Kommas getrennt StringTokenizer tok = new StringTokenizer(cookieString, ";", false); während (tok.hasMoreTokens()) { Zeichenfolgen-Token = tok.nextToken(); // Position des Gleichheitszeichens abrufen int i = token.indexOf("="); wenn (i > -1) { // Name und Wert abrufen und Leerzeichen entfernen String name = token.substring(0, i).trim(); Zeichenfolgenwert = token.substring(i+1, token.length()).trim(); // RFC 2109 und Fehler, entfernen Sie doppelte Anführungszeichen an beiden Enden" Wert = stripQuote(Wert); // Holen Sie ein ServerCookie-Objekt aus dem internen Cookie-Cache-Pool ServerCookie cookie = addCookie(); // Name und Wert festlegen Cookie.getName().setString(name); Cookie.getValue().setString(Wert); } anders { // wir haben einen schlechten Keks... lass ihn einfach weg } } } Nach dem Parsen besteht der nächste Schritt darin, das Cookie mit dem Namen JSESSIONID in der Methode parseSessionCookiesId zu durchlaufen und zu versuchen, es abzugleichen. Wenn es vorhanden ist, wird sein Wert auf die requestedSessionId der Anforderung gesetzt und einem internen Sitzungsobjekt zugeordnet. 2. Session-Cookies generieren Die mit der Sitzung verbundenen Cookies werden von Tomcat selbst generiert. Wenn Request.getSession() im Servlet verwendet wird, um das Sitzungsobjekt abzurufen, wird die Ausführung ausgelöst. Der Kerncode lautet: geschützte Sitzung doGetSession(boolean create) { ... // Eine Sitzungsinstanz erstellen if (connector.getEmptySessionPath() && isRequestedSessionIdFromCookie()) { // Wenn die Sitzungs-ID von einem Cookie stammt, verwenden Sie sie erneut. Wenn sie von einer URL stammt, verwenden Sie sie nicht erneut, um mögliche Phishing-Angriffe zu verhindern. session = manager.createSession(getRequestedSessionId()); } anders { Sitzung = Manager.createSession(null); } //Erstelle ein neues Session-Cookie basierend auf der Session wenn ((Sitzung != null) und (getContext() != null) && getContext().getCookies()) { Zeichenfolge scName = Kontext.getSessionCookieName(); if (scName == null) { //Standard-JSESSIONID scName = Globals.SESSION_COOKIE_NAME; } //Erstelle ein neues Cookie Cookie cookie = neues Cookie(scName, session.getIdInternal()); // Pfaddomäne sicher setzen Konfigurieren Sie SessionCookie (Cookie); // Zum Antwortheaderfeld hinzufügen response.addSessionCookieInternal(cookie, context.getUseHttpOnly()); } wenn (Sitzung != null) { Sitzung.Zugriff(); Rückkehr (Sitzung); } anders { Rückgabe (null); } } Es wird dem Antwortheaderfeld hinzugefügt und entsprechend dem Cookie-Objekt im eingangs beschriebenen Format generiert. 3. Sitzung Session ist eine Schnittstelle innerhalb von Tomcat und eine Fassadenklasse von HttpSession, die verwendet wird, um Statusinformationen zwischen Anfragen bestimmter Benutzer einer Webanwendung aufrechtzuerhalten. Der entsprechende Klassendiagrammentwurf sieht wie folgt aus: Die Funktionen der wichtigsten Klassen bzw. Schnittstellen sind wie folgt:
Dieser Artikel analysiert nicht die Prinzipien der Cluster-Replikation, sondern nur die Verwaltung eigenständiger Sitzungen. 3.1 Sitzung erstellen Wenn Sie Request.getSession() zum ersten Mal verwenden, um ein Sitzungsobjekt in einem Servlet abzurufen, wird eine StandardSession-Instanz erstellt: öffentliche Sitzung erstellenSession(String sessionId) { // Die Standardrückgabe ist eine neue StandardSession(diese)-Instanz. Session session = createEmptySession(); // Eigenschaften initialisieren session.setNew(true); Sitzung.setValid(true); Sitzung.setCreationTime(System.currentTimeMillis()); // Legen Sie die Gültigkeitsdauer der Sitzung in Sekunden fest. Der Standardwert beträgt 30 Minuten. Ein negativer Wert bedeutet, dass die Sitzung nie abläuft. session.setMaxInactiveInterval(((Context) getContainer()).getSessionTimeout() * 60); wenn (Sitzungs-ID == null) { // Eine Session-ID generieren Sitzungs-ID = generateSessionId(); Sitzung.setId(Sitzungs-ID); Sitzungszähler++; SessionTiming-Timing = neues SessionTiming (session.getCreationTime (), 0); synchronisiert (sessionCreationTiming) { sessionCreationTiming.add(Zeitpunkt); Sitzungserstellungstiming.poll(); } Rückkehr (Sitzung); } Der Schlüssel liegt in der Generierung der eindeutigen Sitzungskennung. Sehen wir uns den Generierungsalgorithmus von Tomcat an:
Der Kerncode lautet wie folgt: geschützter String generateSessionId() { byte random[] = neues byte[16]; : Zeichenfolge jvmRoute = getJvmRoute(); String-Ergebnis = null; // Das Ergebnis als Zeichenfolge mit hexadezimalen Zahlen rendern StringBuffer buffer = new StringBuffer(); Tun { int resultLenBytes = 0; if (Ergebnis != null) { // Wiederholen, Puffer neu generieren = neuer StringBuffer(); Duplikate++; } //sessionIdLength ist 16 während (resultLenBytes < this.sessionIdLength) { getRandomBytes(random); // 16 Bytes nach dem Zufallsprinzip abrufen // Zusammenfassung dieser 16 Bytes abrufen, standardmäßig mit MD5 random = getDigest().digest(random); // Durchlaufe dieses Byte-Array und erzeuge schließlich einen 32-Bit-Hexadezimal-String für (int j = 0; j < zufällige Länge und ErgebnislängeBytes < diese Sitzungs-ID-Länge; j++) { // Erzeuge ein hexadezimales Zeichen unter Verwendung der höchsten und niedrigsten 4 Bits des angegebenen Bytes Byte b1 = (Byte) ((random[j] & 0xf0) >> 4); Byte b2 = (Byte) (zufällig[j] & 0x0f); // In hexadezimale Ziffern umwandeln, wenn (b1 < 10) {buffer.append((char) ('0' + b1));} // Hexadezimale Zeichen in Großbuchstaben umwandeln, sonst {buffer.append((char) ('A' + (b1 - 10)));} wenn (b2 < 10) {Puffer.Anhängen((char) ('0' + b2));} sonst {buffer.append((char) ('A' + (b2 - 10)));} ErgebnisLenBytes++; } } if (jvmRoute != null) {buffer.append('.').append(jvmRoute);} Ergebnis = Puffer.toString(); } während (sessions.containsKey(Ergebnis)); Rückgabe (Ergebnis); } 3.2 Überprüfung des Sitzungsablaufs Eine Webanwendung entspricht einem Sitzungsmanager, was bedeutet, dass sich innerhalb von StandardContext eine Managerinstanz befindet. Jede Containerkomponente startet einen Hintergrundthread und ruft regelmäßig die Methode backgroundProcess() von sich selbst und ihren internen Komponenten auf. Die Hintergrundverarbeitung des Managers dient dazu, zu prüfen, ob die Sitzung abgelaufen ist. Die Logik der Prüfung besteht darin, alle Sitzungen abzurufen und anhand ihres isValid zu bestimmen, ob sie abgelaufen sind. Der Code lautet wie folgt: öffentliches Boolean ist gültig() { ... // Ob geprüft werden soll, ob es aktiv ist, der Standardwert ist „false“ wenn (ACTIVITY_CHECK && accessCount.get() > 0) { gibt true zurück; } // Prüfen ob die Zeit abgelaufen ist if (maxInactiveInterval >= 0) { lange ZeitJetzt = System.currentTimeMillis(); int timeIdle = (int) ((Jetztzeit - dieseZugriffszeit) / 1000L); wenn (Leerlaufzeit >= maxInaktivesIntervall) { // Wenn abgelaufen, führe eine interne Verarbeitung durch // Benachrichtige vor allem Listener, die an Ablaufereignissen interessiert sind ablaufen(wahr); } } // Pluralzahlen verfallen nie return (this.isValid); } 3.3 Sitzungspersistenz Persistenz bedeutet, die aktiven Sitzungsobjekte im Speicher in eine Datei zu serialisieren oder in einer Datenbank zu speichern. Wenn die Sitzungsverwaltungskomponente die Anforderungen erfüllt und die Persistenz aktiviert hat, erfolgt die Speicherung in ihrer Lebenszyklusereignis-Stoppmethode; das Laden erfolgt in der Startmethode. Persistenz in Datei. StandardManager bietet auch die Funktion der Persistenz in Datei. Es schreibt alle aktiven Sitzungen im Sitzungspool in die Datei CATALINA_HOME/work/Catalina/<host>/<webapp>/SESSIONS.ser. Der Code befindet sich in seiner doUnload-Methode. FileStore bietet auch die Funktion zum persistenten Speichern von Dateien. Der Unterschied zu StandardManager besteht darin, dass jede Sitzung in eine einzelne Datei mit dem Namen <id>.session geschrieben wird. Bleiben Sie in der Datenbank und speichern Sie sitzungsbezogene Daten in einer Tabelle, einschließlich serialisierter Binärdaten. Die Tabellenfeldinformationen lauten wie folgt: Tabelle tomcat_sessions erstellen ( session_id varchar(100) nicht null Primärschlüssel, valid_session char(1) not null, -- Gültigkeit max_inactive int not null, -- Maximale Gültigkeitsdauer last_access bigint not null, -- Letzter Zugriffszeitpunkt app_name varchar(255), -- Anwendungsname im Format /Engine/Host/Context session_data mediumblob, -- binäre Daten KEY kapp_name (app_name) ); Hinweis: Sie müssen die JAR-Datei des Datenbanktreibers im Verzeichnis $CATALINA_HOME/lib ablegen, um sie für den Klassenlader in Tomcat sichtbar zu machen. 4. Zusammenfassung Dieser Artikel analysiert kurz die Sitzungsverwaltung von Tomcat. Natürlich werden dabei viele Details außer Acht gelassen. Interessierte können sich den Quellcode genauer ansehen. Die Implementierung der Tomcat-Clustersitzung wird später analysiert. Zusammenfassen Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Lernwert für Ihr Studium oder Ihre Arbeit hat. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM. Das könnte Sie auch interessieren:
|
>>: JavaScript implementiert die asynchrone Erfassung von Formulardaten
3 Möglichkeiten zum Implementieren des Tab-Wechse...
Ich habe eine gute Idee gesehen und sie aufgezeic...
Im vorherigen Artikel haben wir drei gängige Meth...
FEHLER 1290 (HY000) : Der MySQL-Server wird mit d...
Die Farbabstimmung beim Erstellen einer Website i...
Inhaltsverzeichnis Vorwort Webpack-Deb-Server Sta...
Inhaltsverzeichnis Überblick Formularvalidierung ...
1. Aufbau einer Einzelmaschinenumgebung# 1.1 Heru...
In diesem Dokument werden die Installations- und ...
1. Nachfrage Das Backend stellt solche Daten bere...
Vorwort Jedes Mal, wenn Sie Docker verwenden, um ...
1. Übersicht Es gibt drei Möglichkeiten, ein Dock...
In diesem Artikelbeispiel wird der spezifische Co...
Inhaltsverzeichnis Vorwort 1. Lokale Portweiterle...
Inhaltsverzeichnis Beispiel 1 Beispiel 2 Beispiel...