TsgcWebSocketHTTPServer | Sessions

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.

 

Konfiguration

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;

 

Sitzung erstellen

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;

Read the Current Session

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;

Verwenden Sie Ihre eigene Session-Klasse

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;

Verwenden Sie Ihre eigene Session-Liste

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;

Ein Hinweis zu OnCreateSession

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.