Freigabe des SQL Server-Sitzungsstatus in Webanwendungen

8

Ich richte eine sehr einfache Demo des SQL Server-Sitzungsstatus ein, habe aber Probleme damit, es zu funktionieren. Ich versuche dies lokal mit Windows 7 mit IIS 7.5 und SQL Server 2008 R2 zu testen.

Letztendlich muss ich die Anzahl der Benutzer protokollieren, die in einem System angemeldet sind, das zwischen einigen verschiedenen Webservern ausgeglichen ist. Daher muss ich eine Sitzungsvariable (in SQL gespeichert) jedes Mal aktualisieren, wenn sich ein Benutzer an- oder abmeldet. Die Sitzungs-ID könnte also immer anders sein. Ist das möglich?

Folgendes habe ich bisher gemacht:

  1. Erstellung von zwei neuen Websites in IIS (Site1 und Site2)
  2. Erstellung von zwei neuen Webanwendungsprojekten in VS 2010 (Site1 und Site2)
  3. In beiden Sites habe ich auf der Default.aspx-Seite eine Schaltfläche erstellt, die beim Klicken entweder "Site1" oder "Site2" (abhängig von der Site) in eine Sitzungsvariable namens "LastSiteUsed" speichert. Es gibt eine weitere Schaltfläche, die beim Klicken den Wert aus der Sitzungsvariablen "LastSiteUsed" liest und in einem Label anzeigt.
  4. In SQL habe ich eine neue Datenbank namens dbSessionTest erstellt. Dann folgte ich den Anweisungen auf MSDN zum Installieren der Sitzungsstatus-Datenbank mit dem aspnet_regsql-Tool . li>
  5. In meiner Web.config-Datei meiner Webanwendung habe ich unter <System.Web> :
  6. Folgendes hinzugefügt

<sessionState mode="SQLServer" sqlConnectionString="server=.\sqlexpress;database=dbSessionTest;uid=myUsername;pwd=myPassword" cookieless="false" timeout="20" allowCustomSqlDatabase="true"/>

Beide Seiten funktionieren normal, aber sie scheinen die Sitzung nicht zu teilen . Wenn ich zum Beispiel auf meine Schaltfläche klicke, um meine Sitzungsvariable von Site1 zu speichern, würde ich erwarten, dass ich diesen Wert von Site2 lesen kann, aber es funktioniert nicht. Site2 wird nur "Site2" zurückgeben und Site1 wird nur "Site1" zurückgeben.

Hat jemand irgendwelche Ideen, was ich falsch machen könnte? Habe ich einen falschen Eindruck, dass ich in der Lage sein sollte, einen von Site1 aus Site2 gesetzten Wert zu lesen?

UPDATE:

Ich kann sehen, dass Sitzungsdaten in der Tabelle ASPStateTempSessions in SQL Management Studio gespeichert werden, aber jeder Standort kann nur den Wert sehen, den er geschrieben hat. Beide Seiten setzen die Sitzungsvariable wie folgt:

%Vor%

Und beide Seiten rufen den Wert wie folgt ab:

%Vor%

Muss ich das für den Zugriff auf in SQL Server gespeicherte Sitzungsvariablen anders machen?

UPDATE 2:

Ich habe versucht, die Standarddatenbank ASPState zu verwenden, die durch Ausführen dieses Befehls erstellt wird:

%Vor%

Dann vereinfacht jede meiner Web.config-Dateien wie:

%Vor%

Aber wieder, kein Glück. Ich möchte in Lage sein, eine Sitzungsvariable von Site1 festzulegen und dann den Wert von Site2 zu lesen, aber es funktioniert nicht. Auch hier kann ich sehen, dass Einträge in der Tabelle ASPStateTempSessions angezeigt werden, damit ich weiß, dass sie richtig eingegeben werden. Eine Sache, die ich bemerkte, ist, dass sie unterschiedliche Sitzungs-IDs haben?

Gibt es etwas, das ich anders machen muss, um sicherzustellen, dass die gleiche Sitzungs-ID zwischen meinen Websites verwendet wird, wenn dieselbe Sitzungsvariable gesetzt / gelesen wird?

UPDATE 3:

Ich habe die Anweisungen von Dieser Artikel ändert einen SP und fügt eine Spalte zum Gruppieren in die Tabelle ASPStateTempApplications hinzu. Diese Art von funktionierte, aber nur, wenn beide meiner Websites im selben Browser geöffnet waren (mit Tabs). Ich muss Site1 im Internet Explorer öffnen, einen Wert für meine Sitzungsvariable speichern, den Browser schließen, Site2 in Chrome öffnen und den Wert lesen können. Von allem, was ich mit SQL Server Session State gelesen habe ... sollte dies möglich sein.

UPDATE 4 - LÖSUNG:

Ich folgte der Antwort auf Dieser Artikel wird von @SilverNinja bereitgestellt. Ich habe die ASPState -Datenbank über die Eingabeaufforderung neu erstellt (um meine SP-Änderungen in Update # 3 rückgängig zu machen) und dann die TempGetAppID SP entsprechend der Antwort vom Link geändert. Ich habe auch beide meiner Web.config-Dateien aktualisiert, um die Antwort aus diesem Artikel ebenfalls zu entsprechen:

%Vor%

Ich habe auch identische Maschinenschlüssel in beide Web.config-Dateien eingefügt:

%Vor%

Jetzt kann ich (mit IE) beide meiner Seiten öffnen, einen Wert von Site1 setzen und ihn von Site2 lesen (und umgekehrt). Wenn ich die Tabelle überprüfe, existiert nur eine SessionID (beide Seiten benutzen dieselbe Session korrekt). Ich lag falsch in meinem Denken, bevor das Öffnen eines neuen Browsers (zum Beispiel mit Chrome) dieselbe Sitzung verwendet - ein neuer Browser startet seine eigene Sitzung. In einem Szenario mit Lastenausgleich sollte dies jedoch keine Probleme verursachen.

    
lhan 29.10.2012, 21:56
quelle

2 Antworten

7

Das Problem, das Sie haben, ist Freigabe des Sitzungsstatus in ASP.NET-Anwendungen . Dies wird nicht sofort mit dem SQL Server-Sitzungsanbieter unterstützt. Sehen Sie sich diese SO-Post zu den Änderungen an, die an den SQL Server-Sitzungsanbieter vorgenommen werden müssen, um anwendungsübergreifende Sitzungen zu unterstützen .

Ich würde keine Sitzung zur Verwaltung dieses gemeinsamen Status verwenden (d. h. LastSiteUsed ). Diese Informationen sollten mit dem Benutzerprofilspeicher ( Mitgliedschaft , Profilanbieter , benutzerdefinierte Datenbank usw. ). Da die Sitzung ablaufen kann, ist die Verwendung einer gemeinsam genutzten Sitzung über mehrere Anwendungen kein zuverlässiger Mechanismus, um den persistenten benutzerspezifischen Status nachzuverfolgen. Wenn Persistenz nicht entscheidend ist, verwenden Sie den AppFabric Cache für ein speicherübergreifender anwendungsübergreifender gemeinsamer Status.

    
SliverNinja 30.10.2012, 17:53
quelle
2

Wenn Sie dieses Problem lösen möchten oder müssen, ohne die gespeicherten Prozeduren der Datenbank zu ändern, sollten Sie diesen Ansatz (nicht für schwache Nerven) in Betracht ziehen.

Die Grundidee ist, dass eine statische Instanz von SqlSessionStateStore.SqlPartitionInfo in System.Web.SessionState.SqlSessionStateStore.s_singlePartitionInfo gespeichert ist, die ich initialisiere, indem ich InitSqlInfo aufruft. Sobald diese Instanz initialisiert ist, setze ich den Wert des internen _appSuffix -Feldes. Die Instanz muss initialisiert werden, bevor das Feld _appSuffix gesetzt wird. Andernfalls wird mein benutzerdefinierter Wert während der Initialisierung überschrieben. Ich berechne den Hash-Code aus dem Anwendungsnamen, der mit derselben Hash-Funktion wie in der ASP.NET-Statusdatenbank bereitgestellt wird.

Beachten Sie, dass dies ungefähr so ​​unangenehm ist, wie es kommt, und vollständig von internen Implementierungsdetails abhängig ist, die sich zu jedem Zeitpunkt ändern können. Ich kenne jedoch keine praktische Alternative. Verwenden Sie nach eigenem Ermessen und Risiko.

Nachdem ich nun meinen Haftungsausschluss angegeben habe, wäre ich überrascht, wenn sich diese Implementierung in .NET BCL geändert hätte, da dieser Authentifizierungsansatz ersetzt wird, und ich sehe keinen Grund für Microsoft, dort zu basteln.

%Vor%     
bart 17.12.2013 23:34
quelle