Unter dem Begriff Session versteht man weitgehend eine Sitzung. Der Anglizismus wird mittlerweile in den verschiedensten Zusammenhängen verwendet. Musiker berichten von einer Albumsproduktion, die in mehreren Sessions durchgeführt worden ist, die Vortragsprogramme bei Konferenzen werden ebenfalls in einzelne Sessions aufgeteilt. Wenn im Webbereich von Sessions die Rede ist, ist damit der Besuch eines Benutzers auf einer Website gemeint. So ein Besuch besteht ja bei Interesse des Benutzers aus mehreren aufeinander folgenden Seitenabrufen. Bei verschiedensten Anwendungen besteht Interesse daran, Informationen während einer solchen Sitzung zwischenzuspeichern. Dies kann eine Liste der Waren sein, die der Benutzer bestellen will oder einfach nur ein anonymer eindeutiger Identifikator, um seinen Weg verfolgen und auswerten zu können.
Unter ASP war das Session-Management noch nicht wirklich konkurrenzfähig; insbesondere der Zwang, Cookies zu verwenden (die der Benutzer im Browser abschalten konnte), verbot den Einsatz bei professionellen Anwendungen. Bei ASP.NET hat sich hier einiges getan, wie Sie in diesem Artikel sehen werden. Wir zeigen Ihnen zunächst ganz allgemein, wie Sie Sessions mit ASP.NET verwenden können und welche erweiterten Optionen Sie haben; dann erstellen wir eine praxisnahe Anwendung, die Sessions verwendet.
Sessions lesen und schreiben
Sessions verwaltet ASP.NET im Session-Objekt. Eine Session besteht aus mehreren Session-Variablen. Jede dieser Variablen kann einen Wert annehmen. Die Session wird gestartet, sobald Sie die erste Session-Variable definieren. Extra Befehle zum Starten der Session sind also nicht notwendig.In C# erzeugen Sie eine Session-Variable mit dem Session-Objekt und hängen in eckigen Klammern und Apostrophen den Variablennamen an. Im folgenden Beispiel eröffnen wir eine Session und definieren zwei Variablen, denen wir jeweils einen String als Wert übergeben:
<script runat="server">void Page_Load() {Session["svar1"] = "Wert1";Session["svar2"] = "Wert2";}</script>
<script runat="server"><br></br> Sub Page_Load()<br></br> Session("Variable1") = "Wert1"<br></br> Session("Variable2") = "Wert2"<br></br> End Sub<br></br></script>
<%@ Page Language="c#" %><script runat="server">void Page_Load() {String var2 = Session["svar2"].ToString();ausgeben.Text = var2;}</script><html><head><title>Session ausgeben</title></head><body><asp:label id="ausgeben" runat="server" /></body></html>
String id = Session.SessionID;
Eine weitere Funktion, die Sie in der Praxis häufig benötigen werden, ist, alle Variablen einer Session auszulesen. Dafür dient die Eigenschaft Contents des Session-Objekts. Diese Eigenschaft ist eigentlich ein Array und enthält die Namen aller Session-Variablen. Sie können auf die Variablen übrigens nicht nur über den Namen, sondern auch über den Index des Arrays, beginnend bei 0, zugreifen.
Mit einer einfachen foreach-Schleife können wir alle Variablen der Session anzeigen:
<%@ Page Language="c#" %><script runat="server">void Page_Load() {foreach (String name in Session.Contents)ausgeben.Text += Session[name] + "<br />";}}</script><html><head><title>Session ausgeben</title></head><body><asp:label id="ausgeben" runat="server" /></body></html>
Auszeit und Schlusspfiff
Eine Session belegt Platz im Arbeitsspeicher des Webservers. Dort soll sie natürlich nicht ewig bleiben, da das Performance kostet und früher oder später den Server zum Absturz bringt. Deswegen muss eine Session beendet werden können. Die eleganteste Lösung ist der Zeitpunkt, wenn ein Nutzer sich ausloggt. In diesem Fall beendet die Methode Abandon des Session-Objekts die aktive Session.Viele Webmail-Dienste meckern, wenn sich der Nutzer beim letzten Mal nicht ausgeloggt hat. Musste die letzte Session dann bis zum erneuten Einloggen auf dem Server vorgehalten werden? Natürlich nicht, denn für eine Session wird ein so genannter Timeout gesetzt. Er legt fest, nach welchem Zeitraum, in dem der Nutzer inaktiv war, die Session abläuft. In ASP.NET können Sie dies mit Session.Timeout für jede Session einzeln festlegen. Die Angabe erfolgt dabei in Minuten. Das folgende Beispiel beendet die Sitzung also, wenn der Nutzer zwei Minuten lang inaktiv war:
<%@ Page Language="c#" %><script runat="server">void Page_Load() {Session["svar1"] = "Wert1";Session.Timeout = 2;}</script>
Wem es zu umständlich ist, das Ablaufen einer Session von Hand anzugeben, der kann dies auch in einer Konfigurationsdatei für das gesamte Webprojekt tun. In ASP.NET heißt diese Datei web.config und muss im Ordner des Webprojekts liegen. Beachten Sie aber, dass der Ordner mit dem Webprojekt im IIS eine Anwendung sein muss.
Sie können diese Konfigurationsdatei mit einem beliebigen Texteditor erzeugen. Das Attribut timeout im sessionState-Tag legt die Ablaufzeit aller Sessions des Projekts in Minuten fest:
<configuration><system.web><sessionState timeout="12" /></system.web></configuration>
Weitere Methoden
Das Session-Objekt bietet neben den bereits bekannten Protagonisten noch einige weitere Methoden. Sie werden sie nicht so oft benötigen, sollten allerdings wissen, dass es sie gibt:- Session.Clear löscht alle Session-Variablen inklusive Wert.
- Session.Remove["name"] entfernt eine Session-Variable.
- Session.Add["name", "Wert"] fügt eine Session-Variable hinzu. Zur oben gezeigten Alternative gibt es keinen funktionalen Unterschied.
Sessions Cookie-los
In ASP war die Verwendung von Sessions immer mit der Verwendung von Cookies verbunden. Auf Cookies können sich viele Website-Betreiber aber nicht einlassen, da der Nutzer sie einfach im Browser deaktivieren kann. Dann funktioniert auf einmal die Nutzerverwaltung mit Warenkorb nicht mehr und der Ärger ist groß.In ASP.NET wurde dieses Problem mit dem Cookie-losen Session-Management gelöst. Ein Eintrag in der Konfigurationsdatei web.config aktiviert es für das gesamte Webprojekt:
<configuration><system.web><sessionState cookieless="true" /></system.web></configuration>
Wenn Sie auf Cookie-loses Session-Management setzen, sind Sie zwar das Cookie-Problem los, haben aber auch neue. Bei Sessions ohne Cookies wird die Session-ID über die URL übertragen (siehe Abb. 1). ASP.NET koppelt die Session-ID automatisch für alle Links auf den Seiten mit der URL. Dies funktioniert aber unter Umständen nicht bei absoluten Links. Ein zweites Problem ohne Cookies ist, dass alles ein wenig langsamer geht. Mit Cookies ist die Performance des Session-Managements ein wenig höher.
Boolean cookies = HttpSessionState.IsCookieLess;
Konfiguration für Fortgeschrittene
Normalerweise werden die Sessions im Arbeitsspeicher des Webservers abgelegt. Das ist bei kleineren Websites auch kein Problem. Schwieriger wird es, wenn die Last des Servers kontinuierlich steigt. ASP.NET löst dieses Problem recht elegant, indem es eine Auslagerung der Sessions per Konfiguration erlaubt. Die Konfigurationseinträge können Sie wiederum entweder nur für ein Projekt in einer web.config-Datei oder global in der machine.config anlegen.ASP.NET hält insgesamt vier Modi bereit, Sessions auszulagern: Die Standardeinstellung ist, Cookies im Arbeitsspeicher des Webservers zu sichern. Dieser Modus heißt mode="InProc". Die Konfigurationsdatei sieht so aus:
<configuration><system.web><sessionState mode="InProc"cookieless="true" /></system.web></configuration>
<configuration><system.web><sessionState mode="SqlServer" sqlConnectionString="data source=127.0.0.1;database=state;user id=sa;password="cookieless="true" /></system.web></configuration>
<configuration><system.web><sessionState mode="StateServer"stateConnectionString="tcpip=127.0.0.1:42424"cookieless="true" /></system.web></configuration>
<configuration><system.web><sessionState mode="Off" /></system.web></configuration>
Beispielapplikation
Personalisierte Portale sind momentan in. In Zeiten, in denen die Werbeumsätze stagnieren oder gar geringer werden, versuchen immer mehr Seitenbetreiber, möglichst genaue Profildaten über ihre Benutzer zu gewinnen und als Gegenleistung Mehrwert zu bieten: Zugriffe auf spezielle Inhalte. Bevor ein Benutzer aber diese Inhalte erhalten darf, muss er sich erst anmelden. Eine Authentifizierung über .NET Passport ist teuer, weswegen einer selbst gestrickten Lösung in vielen Fällen der Vorzug gegeben wird.Wir werden bei dieser Applikation natürlich Sessions einsetzen. In einer Session-Variablen wird der Benutzername des gerade eingeloggten Nutzers abgelegt. Zunächst müssen wir sicherstellen, dass bei Seiten mit personalisiertem Inhalt lediglich authentifizierte Nutzer Zugriff erhalten. Da diese Aufgabenstellung häufig vorkommt - nämlich auf allen personalisierten Seiten - bietet sich eine Code Behind-Klasse geradezu an (Alternative: Ein User Control). Alle personalisierten Seiten erben dann von der Klasse:
<%@ Page Language="c#"Inherits="SessionCodeBehind"Src="SessionCodeBehind.cs" %><html><head><title>Personalisierter Bereich</title></head><body><h1>Willkommen in Ihrem personalisierten Bereich!</h1><p>Benutzer: <asp:Label id="Benutzer" runat="server" /></p><p><a href="logout.aspx">Logout</a></p></body></html>
public void Page_Load(Object o, EventArgs e) {if (Session["login"] == null ||Session["login"] == "") {String referer = Request.ServerVariables["SCRIPT_NAME"];Response.Redirect("login.aspx?ref=" + referer);}}
Benutzer.Text = HttpUtility.HtmlEncode(Session["login"].ToString());
using System;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;public class SessionCodeBehind : Page {public Label Benutzer;public void Page_Load(Object o, EventArgs e) {if (Session["login"] == null ||Session["login"] == "") {String referer = Request.ServerVariables["SCRIPT_NAME"];Response.Redirect("login.aspx?ref=" + referer);} else {Benutzer.Text = HttpUtility.HtmlEncode(Session["login"].ToString());}}}
- id - AutoWert (ID des Eintrags)
- login - Text (Benutzername)
- passwort - Text (zugehöriges Passwort)
<form runat="server"><p><asp:Label id="Ausgabe" runat="server" /></p><p>Benutzer: <asp:TextBox id="Benutzer" runat="server" /></p><p>Passwort: <asp:TextBox TextMode="Password" id="Passwort" runat="server" /></p><p><asp:Button Text="Login" OnClick="Login" runat="server" /></form>
public void Login(Object o, EventArgs e) {OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0; Data Source=c:\\inetpub\\db\\sessions.mdb");conn.Open();OleDbCommand comm = new OleDbCommand("SELECT * FROM benutzer WHERE login LIKE '" +Benutzer.Text.Replace("'", "''") +"' AND passwort = '" +Passwort.Text.Replace("'", "''") +"'", conn);OleDbDataReader reader = comm.ExecuteReader();
if (reader.Read()) {Session["login"] = Benutzer.Text;conn.Close();if (Request.QueryString["ref"] != null) {Response.Redirect(Request.QueryString["ref"]);} else {Response.Redirect("./");}}
else {Ausgabe.Text = "Login gescheitert";conn.Close();}
<%@ Page Language="c#" %><%@ Import Namespace="System.Data" %><%@ Import Namespace="System.Data.OleDb" %><script runat="server">public void Login(Object o, EventArgs e) {OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0; Data Source=c:\\inetpub\\db\\sessions.mdb");conn.Open();OleDbCommand comm = new OleDbCommand("SELECT * FROM benutzer WHERE login LIKE '" +Benutzer.Text.Replace("'", "''") +"' AND passwort = '" +Passwort.Text.Replace("'", "''") +"'", conn);OleDbDataReader reader = comm.ExecuteReader();if (reader.Read()) {Session["login"] = Benutzer.Text;conn.Close();if (Request.QueryString["ref"] != null) {Response.Redirect(Request.QueryString["ref"]);} else {Response.Redirect("./");}} else {Ausgabe.Text = "Login gescheitert";conn.Close();}}</script><html><head><title>Personalisierter Bereich</title></head><body><h1>Login</h1><form runat="server"><p><asp:Label id="Ausgabe" runat="server" /></p><p>Benutzer: <asp:TextBox id="Benutzer" runat="server" /></p><p>Passwort: <asp:TextBox TextMode="Password" id="Passwort" runat="server" /></p><p><asp:Button Text="Login" OnClick="Login" runat="server" /></form></body></html>
<%@ Page Language="c#"%><script runat="server">public void Page_Load(Object o, EventArgs e) {Session["login"] = "";}</script><html><head><title>Personalisierter Bereich</title></head><body><h1>Sie haben den personalisierten Bereich verlassen!</h1><p><a href="login.aspx">Login</a></p></body></html>
Fazit
Diese kleine, aber feine Applikation hat Ihnen gezeigt, wie Sie mit ASP.NET und dem eingebauten Session-Management den Grundstein für eine Anwendung legen können, die unbedingt ein Session-Management benötigt. Personalisierung ist nur der erste Schritt.Im nächsten Heft gehen wir auf die zweite Möglichkeit für eine Webapplikation ein, Informationen zu behalten. Die Rede ist natürlich von Cookies, den kleinen, ungeliebten Datenkrümeln.


