HTTP ist ein zustandsloses Protokoll (zumindest bis HTTP 1.1), daher fordert der Client eine Datei an, der Server sendet eine Antwort, und die Verbindung wird geschlossen (Sie können Keep-Alive aktivieren, sodass die Verbindung nicht sofort geschlossen wird, aber das geht über den Rahmen dieses Artikels hinaus). Sitzungen ermöglichen es Ihnen, Informationen über den Client zu speichern, die zum Beispiel während einer Client-Anmeldung verwendet werden können. Sie können eine beliebige eindeutige Sitzungs-ID verwenden, die Liste der Sitzungen durchsuchen, um zu sehen, ob bereits eine existiert, und falls nicht, eine neue Sitzung erstellen. Eine Sitzung kann nach einer Inaktivitätsperiode oder manuell nach der Client-Abmeldung zerstört werden.
Es gibt einige Eigenschaften in TsgcWebSocketHTTPServer, die Sitzungen in der Server-Komponente aktivieren/deaktivieren. Die wichtigsten sind:
| Eigenschaft | Beschreibung |
| SessionState | Dies ist die erste Eigenschaft, die aktiviert werden muss, um Sitzungen zu verwenden. Ohne aktivierte Eigenschaft funktionieren Sitzungen nicht |
|
SessionTimeout |
Hier müssen Sie einen Wert größer als null (in Millisekunden) für die maximale Zeit festlegen, die eine Sitzung aktiv sein wird. |
| AutoStartSession | Sitzungen können automatisch (AutoStartSession = true) oder manuell (AutoStartSession = false) erstellt werden. Wenn Sitzungen automatisch erstellt werden, verwendet der Server RemoteIP als eindeutigen Bezeichner, um zu prüfen, ob eine aktive Sitzung gespeichert ist. |
| SessionClass | Optional. Die Klasse, die der Server beim Erstellen einer neuen Sitzung verwendet. Setzen Sie sie auf Ihre eigene TIdHTTPSession-Abkömmlingsklasse, um eigene Daten innerhalb jeder Sitzung zu speichern. Muss gesetzt werden, bevor der Server aktiviert wird. |
| SessionList | Die Liste, die die aktiven Sitzungen enthält. Lesen Sie sie, um Sitzungen per Code zu suchen, zu erstellen oder zu entfernen. Sie können auch Ihre eigene Liste zuweisen, wenn Sie die volle Kontrolle darüber benötigen, wo Sitzungen gespeichert werden. Muss vor der Aktivierung des Servers zugewiesen werden. |
TsgcWebSocketHTTPServer1.SessionState := True;
TsgcWebSocketHTTPServer1.SessionTimeout := 600000;
TsgcWebSocketHTTPServer1.AutoStartSession := False;
Um eine neue Sitzung zu erstellen, müssen Sie eine neue Session-ID erstellen, die eindeutig ist. Sie können jeden Wert verwenden. Beispiel: Wenn sich der Client authentifiziert, können Sie user + password + remoteip als Session-ID verwenden.
Durchsuchen Sie dann die Sitzungsliste, um zu prüfen, ob sie bereits existiert. Wenn sie nicht existiert, erstellen Sie eine neue.
Wenn eine neue Sitzung erstellt wird, wird das Ereignis OnSessionStart aufgerufen, und wenn die Sitzung geschlossen wird, wird das Ereignis OnSessionEnd ausgelöst.
procedure OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
var
vID: String;
oSession: TIdHTTPSession;
begin
if ARequestInfo.Document = '/' then
AResponseInfo.ServeFile(AContext, 'yourpathhere\index.html')
else
begin
// check if user is valid
if not ((ARequestInfo.AuthUsername = 'user') and (ARequestInfo.AuthPassword = 'pass')) then
AResponseInfo.AuthRealm := 'Authenticate'
else
begin
// create a new session id with authentication data
vID := ARequestInfo.AuthUsername + '_' + ARequestInfo.AuthPassword + '_' + ARequestInfo.RemoteIP;
// search session
oSession := TsgcWebSocketHTTPServer1.SessionList.GetSession(vID, ARequestInfo.RemoteIP);
// create new session if not exists
if not Assigned(oSession) then
oSession := TsgcWebSocketHTTPServer1.SessionList.CreateSession(ARequestInfo.RemoteIP, vID);
AResponseInfo.ContentText := '<html><head></head><body>Authenticated</body></html>';
AResponseInfo.ResponseNo := 200;
end;
end;
end;
Sobald eine Sitzung existiert, hängt der Server sie an jede Anfrage an, die das Sitzungscookie trägt. Lesen Sie sie aus ARequestInfo.Session, das nil ist, wenn die Anfrage keine Sitzung hat.
procedure OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
begin
if Assigned(ARequestInfo.Session) then
begin
// Content is a TStrings you can use to store your own values
ARequestInfo.Session.Content.Values['visits'] :=
IntToStr(StrToIntDef(ARequestInfo.Session.Content.Values['visits'], 0) + 1);
AResponseInfo.ContentText := 'Session ' + ARequestInfo.Session.SessionID +
' visits: ' + ARequestInfo.Session.Content.Values['visits'];
end
else
AResponseInfo.ContentText := 'No session';
end;
Wenn Sie eigene Felder innerhalb jeder Sitzung führen möchten, statt die Content-Zeichenfolgenliste zu verwenden, erstellen Sie einen Abkömmling von TIdHTTPSession und weisen Sie den Server über die Eigenschaft SessionClass an, ihn zu verwenden. Setzen Sie dies bevor der Server aktiviert wird.
Der Server kümmert sich weiterhin um alles Weitere: Er erzeugt die eindeutige Sitzungs-ID, sendet das Sitzungs-Cookie, wendet SessionTimeout an und entfernt veraltete Sitzungen. Überschreiben Sie den virtuellen Konstruktor CreateInitialized, wenn Sie eigene Felder initialisieren möchten, wenn die Sitzung erstellt wird.
type
TMySession = class(TIdHTTPSession)
private
FUserName: String;
FLoginTime: TDateTime;
public
constructor CreateInitialized(AOwner: TIdHTTPCustomSessionList;
const SessionID, RemoteIP: string); override;
property UserName: String read FUserName write FUserName;
property LoginTime: TDateTime read FLoginTime write FLoginTime;
end;
constructor TMySession.CreateInitialized(AOwner: TIdHTTPCustomSessionList;
const SessionID, RemoteIP: string);
begin
inherited CreateInitialized(AOwner, SessionID, RemoteIP);
FLoginTime := Now;
end;
// configure the server before it starts
TsgcWebSocketHTTPServer1.SessionState := True;
TsgcWebSocketHTTPServer1.SessionTimeout := 600000;
TsgcWebSocketHTTPServer1.SessionClass := TMySession;
TsgcWebSocketHTTPServer1.Active := True;
// and read it back in any request
procedure OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
begin
if ARequestInfo.Session is TMySession then
AResponseInfo.ContentText := TMySession(ARequestInfo.Session).UserName;
end;
Wenn Sie die volle Kontrolle darüber benötigen, wie Sessions gespeichert werden, zum Beispiel um sie in einer Datenbank zu halten oder zwischen mehreren Servern zu teilen, weisen Sie der Eigenschaft SessionList Ihre eigene Liste zu, bevor der Server aktiviert wird. Leiten Sie von TIdHTTPDefaultSessionList ab und überschreiben Sie die virtuelle Methode CreateSession. Der Server ruft sie intern aus CreateUniqueSession auf, sodass die eindeutige Session-ID weiterhin für Sie erzeugt wird.
Wenn Sie Ihre eigene SessionList zuweisen, gilt die Eigenschaft SessionClass nicht mehr, da Ihre Liste entscheidet, welche Klasse erstellt wird.
type
TMySessionList = class(TIdHTTPDefaultSessionList)
public
function CreateSession(const RemoteIP, SessionID: string)
: TIdHTTPSession; override;
end;
function TMySessionList.CreateSession(const RemoteIP, SessionID: string)
: TIdHTTPSession;
begin
Result := TMySession.CreateInitialized(Self, SessionID, RemoteIP);
SessionList.Add(Result);
end;
// assign it before the server starts
TsgcWebSocketHTTPServer1.SessionList := TMySessionList.Create(nil);
TsgcWebSocketHTTPServer1.Active := True;
Das Ereignis OnCreateSession ermöglicht es Ihnen, selbst eine Sitzungsinstanz zurückzugeben, weist ihr jedoch keine Sitzungs-Id zu. Wenn Sie die Sitzung mit einem einfachen Konstruktor erstellen, sind die Sitzungs-Id und das Sitzungs-Cookie leer, und die Sitzung kann bei der nächsten Anfrage nie wieder gefunden werden. Verwenden Sie stattdessen SessionClass, das einfacher ist und all das für Sie erledigt.
Rufen Sie außerdem SessionList.CreateUniqueSession nicht innerhalb von OnCreateSession auf. Diese Methode fügt die neue Session bereits zur Liste hinzu, und der Server fügt sie erneut hinzu, wenn Ihr Handler zurückkehrt, sodass dieselbe Session doppelt in der Liste landet.