Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einleitung
2 Webbrowser
3 JavaScript einbauen
4 Programmieren mit JavaScript
5 Datum
6 Zufall
7 Browserinformationen
8 Fenster
9 Formulare
10 Frames und Iframes
11 Grafiken
12 Cookies
13 Objekte und Arrays
14 Ereignisbehandlung
15 Fehlerbehandlung
16 DOM
17 DHTML und CSS
18 AJAX
19 XML
20 Web Services
21 AJAX-Frameworks
22 Plugins
23 Multimedia
24 Java
25 Serverseitige Technologien
26 JavaScript goes .NET
27 Code schützen
28 Top Secret: Passwortschutz
29 Signierte Skripte
30 JavaScript und Sicherheit
31 Navigation
32 Warenkorb
33 JavaScript-Bibliotheken
34 Referenz
35 Quellen im Web
36 Die Zukunft von JavaScript
Index
Download: - ZIP, ca. 9,2 MB
Buch bestellen
Ihre Meinung?
<< zurück | Galileo Computing / <openbook> / JavaScript und AJAX | vor >>
JavaScript und AJAX von Christian Wenz Das umfassende Handbuch
JavaScript und AJAX 839 S., mit DVD, 39,90 Euro Galileo Computing ISBN 3-89842-859-1 |
| Kapitel 12 Cookies
|  | 12.1 Was ist ein Cookie?
|  | 12.2 Wie sieht ein Cookie aus?
|  | 12.3 Cookies mit JavaScript
|  |  | 12.3.1 Cookies setzen
|  |  | 12.3.2 Cookies löschen
|  |  | 12.3.3 Cookies lesen
|  |  | 12.3.4 Cookie-Unterstützung überprüfen
|  |  | 12.3.5 Ein Cookie statt vieler Cookies
## 12.3 Cookies mit JavaScript Cookies werden mit JavaScript in der Eigenschaft cookie des document-Objekts gespeichert, und zwar als Zeichenkette. Das impliziert, dass man auf Cookies nicht wie auf Objekte mit Eigenschaften und Methoden zugreifen kann. Beim Setzen des Cookies ist das kein weiteres Problem, da denkt der JavaScript-Interpreter mit. Wenn der Wert von document. cookie beispielsweise
    "Autor=Christian+Wenz"
ist und der Befehl
    document.cookie = "Verlag=Galileo";
ausgeführt wird, lautet der Wert von document.cookie danach folgendermaßen:
    Autor=Christian+Wenz; Verlag=Galileo
Der JavaScript-Interpreter passt den Wert des Cookies also automatisch an. Das gilt auch, wenn der Wert eines Cookies geändert wird. Nach der Ausführung des Befehls
    document.cookie = "Verlag=Galileo-Press";
wird der Wert von document.cookie in
    Autor=Christian+Wenz; Verlag=Galileo-Press
geändert. Der Internet Explorer unterstützt auch Cookies, die nur vom Webserver gesetzt und ausgelesen werden können, jedoch nicht von JavaScript. Hinter diesen Cookies steht die Idee, kein Cookie-Auslesen per XSS zu ermöglichen (siehe Kapitel 30). ### 12.3.1 Cookies setzen Es bietet sich an, zum Setzen eines Cookies eine Funktion zu schreiben, an die die einzelnen Parameter des Cookies als Funktionsparameter übergeben werden. Im Folgenden ist so eine Funktion aufgeführt: Es wird überprüft, ob der jeweilige Parameter den Wert null hat (also nicht angegeben worden ist), und dementsprechend wird der Cookie angepasst.
    function setCookie(name, wert, domain, expires, path, secure){
       var cook = name + "=" + unescape(wert);
       cook += (domain) ? "; domain=" + domain : "";
       cook += (expires) ? "; expires=" + expires : "";
       cook += (path) ? "; path=" + path : "";

       cook += (secure) ? "; secure" : "";
       document.cookie = cook;
    }
Der Beispielaufruf
    setCookie("Autor", "Christian Wenz", null, (new Date()).getTime() + 1000*3600*24).toGMTString())
setzt einen Cookie Autor=Christian+Wenz, der einen Tag lang gültig ist (1000 Millisekunden pro Sekunde, 3600 Sekunden pro Stunde, 24 Stunden pro Tag). ### 12.3.2 Cookies löschen Das Löschen von Cookies ist auch sehr bequem. Man versetzt hierbei das Ablaufdatum in die Vergangenheit. Damit wird der Cookie danach sofort ungültig und gelöscht. Zwar könnte man das aktuelle Datum nehmen und einen Tag oder sogar nur eine Sekunde davon abziehen, aber in der Regel setzt man das Ablaufdatum auf die frühestmögliche Zeit unter JavaScript, den 1. Januar 1970, eine Sekunde nach Mitternacht. In GMT-Schreibweise sieht das so aus:
    Thu, 01-Jan-70 00:00:01 GMT
Beim Schreiben einer Funktion müssen Sie die Parameter für die Domain und den Pfad ebenfalls mit angeben können, um gegebenenfalls den richtigen Cookie zu löschen:
    function eraseCookie(name, domain, path) {
       var cook="name=; expires=Thu, 01-Jan-70 00:00:01 GMT";
       cook += (domain) ? "domain=" + domain : "";
       cook += (path) ? "path=" + path : "";
       document.cookie = cook;
    }
### 12.3.3 Cookies lesen Kommen wir zum schwierigsten Teil: den Wert eines Cookies wieder zu lesen. Wie ich bereits zuvor angedeutet habe, wird der Sonderfall zweier gleichnamiger Cookies mit unterschiedlicher Pfadangabe hier nicht berücksichtigt, weil der Aufwand unverhältnismäßig steigt. Stattdessen wird der zu schreibenden Funktion, die den Wert eines Cookies zurückgeben soll, nur der Name des Cookies übergeben, sonst nichts. Der erste Cookie, der dann gefunden wird, wird angezeigt. Bei dieser Aufgabenstellung sieht man erst den Nachteil, dass man auf Cookies nicht als Objekte zugreifen kann. Der Wert des Cookies muss mit profanen Stringfunktionen herausgefunden werden. Das ist aber recht einfach: Zuerst wird nach der Zeichenkette "name=" gesucht, wobei name den Namen des Cookies angibt. Dahinter steht dann der Wert des Cookies. Sobald man auf ein Semikolon oder das Ende der Zeichenkette stößt, hat man den gesamten Wert und kann ihn (aus der URL-Schreibweise wieder zurückcodiert) zurückgeben.
    function getCookie(name) {
       var i=0;  //Suchposition im Cookie
       var suche = name + "=";
       while (i<document.cookie.length) {
          if (document.cookie.substring(i, i + suche.length)
          == suche) {
             var ende = document.cookie.indexOf(";", i
             + suche.length);
             ende = (ende > –1) ? ende :
             document.cookie.length;
             var cook = document.cookie.substring(i
                + suche.length, ende);
             return unescape(cook);
          }
          i++;
       }
       return "";
    }
Der zweite Parameter bei open() gibt die Position an, ab der gesucht werden soll. Wird kein zweiter Parameter angegeben (wie das bis dato bei allen Beispielen der Fall war), wird die Zeichenkette von Anfang an (also ab dem Zeichen mit der Position 0) durchsucht. ### 12.3.4 Cookie-Unterstützung überprüfen Aufgrund der eingangs angedeuteten Paranoia bezüglich Cookies haben viele Benutzer die Verwendung von Cookies abgeschaltet, oder sie lassen ein Warnfenster ausgeben, sobald ein Cookie vom Server (oder hier vom Browser selbst) geschickt wird. Aus diesem Grund sollte man – zumindest am Anfang einer auf Cookies basierenden Applikation – prüfen, ob Cookies unterstützt werden. An vielen Stellen wurde vorgeschlagen, folgende Überprüfung vorzunehmen:
    if (document.cookie) {
       // Cookie-Code
    }
Hier klicken, um das Bild zu Vergrößern Abbildung 12.1 Die Cookie-Warnung eines Browsers Prinzipiell ist der Ansatz gar nicht schlecht, aber oft wurde einfach behauptet, so werde überprüft, ob das Cookie-Objekt unterstützt wird. Das ist leider völlig falsch, denn document.cookie ist kein Objekt, sondern einfach eine (sehr funktionsfähige, man denke an die Zuweisungen) Zeichenkette. Aus diesem Grund ist hier die if-Abfrage nur eine Abkürzung für folgenden Code:
    if (document.cookie.length > 0){
       // Cookie-Code
    }
Die erste Variante ist deswegen recht verbreitet, weil es vielleicht einmal Browser gibt, bei denen document.cookie gleich null ist – und dann führt ein Zugriff auf die Eigenschaft length zu einem Fehler. Aber zurück zum Thema. Die obigen Abfragen überprüfen, ob document.cookie mindestens ein Zeichen enthält. Aus diesem Grund kann man mit obiger Methode also nicht testen, ob der Browser Cookies unterstützt, sondern nur, ob schon ein Cookie gesetzt worden ist. Sie müssen also einen Cookie setzen, um herauszufinden, ob der Browser ihn annimmt – also »Trial and Error«. Eine Funktion, die überprüft, ob der Benutzer Cookies überhaupt akzeptiert, ist folgende:
    function checkCookie() {
       setCookie("CookieTest", "OK");
       if (!getCookie("CookieTest")) {
          return false;
       } else {
          eraseCookie("CookieTest");
          return true;
       }
    }
Hier sehen Sie einen Vorteil von JavaScript gegenüber serverseitigen Programmiersprachen: Bei der zuletzt dargestellten Vorgehensweise kann man nur übermittelte Cookies auslesen und dann neue Cookies setzen. Um aber nach dem Setzen zu überprüfen, ob das auch funktioniert hat, muss man eine neue Seite aufrufen bzw. ein neues Skript ausführen. Hier klicken, um das Bild zu Vergrößern Abbildung 12.2 Ab Internet Explorer 5 gibt es detaillierte Einstellungsmöglichkeiten für Cookies – in anderen Browsern schon länger. Diese Funktion sollten Sie jedoch nicht allzu oft ausführen. Viele Benutzer lassen sich einfach eine Warnmeldung anzeigen, um beispielsweise zu sehen, was in dem Cookie steht. Auf vielen Seiten benötigen Sie zwar beispielsweise den Cookie der Site selbst (beispielsweise Ihre Kundennummer), nicht aber den Cookie des Werbebanners auf derselben Site. Wenn Sie nun diese Funktion auf jeder Seite ausprobieren, ärgern sich die Benutzer über die vielen Warnmeldungen. In diesem Zusammenhang ein kleiner Hinweis: Paranoia hin oder her, die Spionagegefahr durch temporäre Cookies ist wirklich gering. Außerdem benötigt beispielsweise Hotmail unbedingt temporäre Cookies, um zu funktionieren (Yahoo! Mail erforderte zeitweise sogar permanente Cookies, inzwischen benötigt man nur noch temporäre Cookies). Der Internet Explorer 5 sowie seine Nachfolgerversionen unterscheiden zwischen diesen beiden Arten von Cookies, und eine empfehlenswerte Einstellung ist, temporäre Cookies immer anzunehmen, bei permanenten Cookies jedoch nachzufragen. Bei neueren Netscape-Versionen ist sogar ein noch detaillierteres Cookie-Management möglich. Vor temporären Cookies muss aber wirklich niemand Angst haben. ### 12.3.5 Ein Cookie statt vieler Cookies Wie bereits mehrfach erwähnt wurde, ist die Anzahl von Cookies beschränkt, zumindest per Spezifikation: Es gibt 300 Cookies insgesamt, aber nur 20 Cookies pro Domain. Dieses Wissen scheint nicht weit verbreitet zu sein, da man oft sieht, dass manche Webmaster auf ihren Seiten mehrere Cookies setzen. In einem Cookie stehen 4 kByte zur Verfügung, also über 4000 Zeichen – ein Wert, der so gut wie nie ausgereizt wird. Es liegt also die Idee nahe, in einem einzelnen Cookie mehrere Informationen zu speichern. Das Hauptproblem hierbei besteht darin, die Informationen in einem einzigen String zusammenzufassen. Andere Programmiersprachen bieten hierzu Hilfsfunktionen zum Zusammenfassen der Daten an (das nennt man unter anderem auch »Serialisierung«). Bei JavaScript müssen wir uns selbst behelfen. Der hier vorgeschlagene Weg funktioniert wie folgt:
| Die Daten werden in einem assoziativen Array abgespeichert.
| Das assoziative Array wird wie folgt in einen String umgewandelt: Es wird ein neues Array erstellt, in das nacheinander die Schlüssel und dazugehörigen Werte des assoziativen Arrays eingefügt werden. Dieser Aufwand ist nötig, da die Methode toString() bei assoziativen Arrays eine leere Zeichenkette zurückliefert.
| Das Array wird dann mit der Methode toString() in eine Zeichenkette umgewandelt; das Ergebnis dient als Wert des Cookies.
Das Lesen von Informationen aus dem Cookie erfolgt ähnlich:
| Die Zeichenkette – gleichzeitig der Inhalt des Arrays – wird aus dem Cookie eingelesen.
| Mit der eval()-Methode wird die Zeichenkette in ein Array umgewandelt.
| Eine Schleife durchläuft das Array und erstellt daraus ein assoziatives Array.
Der Code ist in vier Funktionen aufgeteilt:
| Die Funktion laden_collection() lädt die Daten aus dem Cookie. Als Cookie-Name wird "daten" verwendet. Der Cookie wird eingelesen, und die Zeichenkette wird in ein Array umgewandelt; dazu werden die einzelnen Array-Elemente mit Anführungszeichen umgeben und eckige Klammern um das Ganze geschrieben:
>     str = str.replace(/,/g, "\",\""); //Anführungszeichen
>     str = "\"" + str + "\"" //Anführungszeichen
>     eval("temp = [" + str + "]");
Mit einer Schleife wird daraus das assoziative Array aufgebaut und zurückgegeben.
| Die Funktion lesen_collection() liest einen einzelnen Wert aus der Collection. Der Name des Wertes wird dabei als Parameter übergeben. Durch einen Aufruf von laden_collection() werden alle Cookie-Daten eingelesen und zurückgegeben; lesen_collection() muss dann nur noch den korrekten Wert auswählen und zurückgeben.
| Die Funktion speichern_collection() erwartet als Parameter ein assoziatives Array. Dieses Array wird zunächst in ein »normales« Array umgewandelt: Zunächst setzen Sie den Schlüssel, dann den dazugehörigen Wert, und das für alle Elemente:
>     for (var e in c) {
>       temp.push(e);
>       temp.push(c[e]);
>     }
> Um eine maximale Browserunabhängigkeit mit alten Browsern (die kein push() kennen) zu erreichen, müssen Sie die Elemente wie folgt einfügen:
>     for (var e in c) {
>       temp[temp.length] = e;
>       temp[temp.length] = c[e];
>     }
Anfangs hat das Array keine Elemente, also die Länge 0. Das nächste Element hat daher den Index 0. Allgemein gesagt: Wenn Sie an ein Array a ein Element anfügen möchten, müssen Sie einfach a[a.length] setzen.Das resultierende Array wird mit toString() in eine Zeichenkette umgewandelt, und diese wird als Wert für den Cookie namens daten verwendet. Das Setzen des Cookies erfolgt mit einer (universellen) Funktion cookie_setzen().
| Die Funktion schreiben_collection() schließlich ändert ein einzelnes Element in der Collection. Als Parameter werden der Name des Elements und der gewünschte Wert übergeben. Die Funktion besteht nur aus drei Kommandos: Zunächst wird mit laden_collection() die Collection geladen, dann wird im resultierenden assoziativen Array der angegebene Wert gesetzt (oder geändert, sollte er bereits existieren). Das modifizierte Array wird an speichern_collection() übergeben und somit wieder im Cookie gespeichert.
Nach diesen detaillierten Vorüberlegungen schreiben sich die Funktionen wie von selbst; Sie finden sie im Folgenden abgedruckt und natürlich auch auf der DVD-ROM zum Buch.
    function cookie_setzen() {
      var anzParameter = cookie_setzen.arguments.length;
      var parameter = cookie_setzen.arguments;
      // 1. Cookie-Name
      var name = parameter[0];
      // 2. Cookie-Wert
      var value = (anzParameter >= 2) ? parameter[1] : "";
      value = escape(value); // URL-Codierung
      // 3. Haltbarkeitsdatum
      var expires = (anzParameter >= 3) ? parameter[2] : null;
      if (expires != null) {
        if (expires.toGMTString) {
          expires = expires.toGMTString();
        }
      }
      // 4. Domain
      var domain = (anzParameter >= 4) ? parameter[3] : null;
      // 5. Pfad
      var path = (anzParameter >= 5) ? parameter[4] : null;

      if (path != null) {
        path = escape(path); // Sonderzeichen umwandeln
      }
      // 6. Sicherheitsstufe
      var secure = (anzParameter >= 6) ? parameter[5] : null;
      // Zusammensetzen des Cookies
      var c = name + "=" + escape(value);
      if (expires != null) {
        c += "; expires=" + expires;
      }
      if (domain != null) {

        c += "; domain=" + domain;
      }
      if (path != null) {
        c += "; path=" + path;
      }
      if (secure) {
        c += "; secure";
      }
      // Cookie setzen
      document.cookie = c;
    }

    function cookie_lesen(name) {
      var i = document.cookie.indexOf(name + "=");
      var c = "";
      if (i > –1) {
        var ende = document.cookie.indexOf("; ",
                   i+name.length+1);
        if (ende == –1) {
          ende = document.cookie.length;
        }
        c = document.cookie.substring(i+name.length+1, ende);
      }
      return unescape(c);
    }

    function laden_collection() {
       var str = cookie_lesen("daten");
       str = unescape(str);
       var temp = new Array();
       // Daten aus dem Cookie in ein Array umwandeln
       if (str != "") {
          str = str.replace(/,/g, "\",\"");
          str = "\"" + str + "\""
          eval("temp = [" + str + "]");
       }
       // assoziatives Array erstellen
       var c = new Array();
       for (var i=0; i<temp.length; i+=2) {
         c[temp[i]] = temp[i+1];
       }
       // Array zurückgeben
       return c;
    }

    function lesen_collection(name) {
       var c = laden_collection();
       return c[name];
    }

    function speichern_collection(c) {
       var temp = new Array();
       for (var e in c) {
          temp[temp.length]=e;
          temp[temp.length]=c[e];
       }
       cookie_setzen("daten", temp.toString());
    }

    function schreiben_collection(name, wert) {
       var c = laden_collection();
       c[name] = wert;
       speichern_collection(c);
    }
Zur Verdeutlichung folgt hier noch ein kleines Beispiel:
    <html>
    <head>
    <title>Cookie-Collection</title>
    </head>
    <body>
    <script type="text/javascript"><!--
    function cookie_setzen() {
       var anzParameter = cookie_setzen.arguments.length;
       var parameter = cookie_setzen.arguments;
       // 1. Cookie-Name
       var name = parameter[0];
       // 2. Cookie-Wert
       var value = (anzParameter >= 2) ? parameter[1] : "";
       value = escape(value); // URL-Codierung
       // 3. Haltbarkeitsdatum
       var expires = (anzParameter >= 3) ? parameter[2] : null;
       if (expires != null) {
          if (expires.toGMTString) {
             expires = expires.toGMTString();
          }
       }
       // 4. Domain
       var domain = (anzParameter >= 4) ? parameter[3] : null;

       // 5. Pfad
       var path = (anzParameter >= 5) ? parameter[4] : null;

       if (path != null) {
          path = escape(path); // Sonderzeichen umwandeln
       }
       // 6. Sicherheitsstufe
       var secure = (anzParameter >= 6) ? parameter[5] : null;
       // Zusammensetzen des Cookies
       var c = name + "=" + escape(value);
       if (expires != null) {
          c += "; expires=" + expires;
       }
       if (domain != null) {
          c += "; domain=" + domain;
       }
       if (path != null) {
          c += "; path=" + path;
       }
       if (secure) {
          c += "; secure";
       }
       // Cookie setzen
       document.cookie = c;
    }

    function cookie_lesen(name) {
       var i = document.cookie.indexOf(name + "=");
       var c = "";
       if (i > –1) {
          var ende = document.cookie.indexOf("; ",
                     i+name.length+1);
          if (ende == –1) {
             ende = document.cookie.length;
          }
          c = document.cookie.substring(i+name.length+1, ende);
       }
       return unescape(c);
    }

    function laden_collection() {
       var str = cookie_lesen("daten");
       str = unescape(str);
       var temp = new Array();
       // Daten aus dem Cookie in ein Array umwandeln
       if (str != "") {
          str = str.replace(/,/g, "\",\"");
          str = "\"" + str + "\""
          eval("temp = [" + str + "]");
       }
       // assoziatives Array erstellen
       var c = new Array();
       for (var i=0; i<temp.length; i+=2) {
         c[temp[i]] = temp[i+1];
       }
       // Array zurückgeben
       return c;
    }

    function lesen_collection(name) {
       var c = laden_collection();
       return c[name];
    }

    function speichern_collection(c) {
       var temp = new Array();
       for (var e in c) {
          temp[temp.length]=e;
          temp[temp.length]=c[e];
       }
       cookie_setzen("daten", temp.toString());
    }

    function schreiben_collection(name, wert) {
       var c = laden_collection();
       c[name] = wert;
       speichern_collection(c);
    }

       schreiben_collection("Autor", "Christian Wenz");
       schreiben_collection("Verlag",
          "Galileo Computing");
       schreiben_collection("Verlag", "Galileo Press");
       var autor = lesen_collection("Autor");
       var verlag = lesen_collection("Verlag");
       document.write("Autor: " + autor + "<br />\n");
       document.write("Verlag: " + verlag + "\n");
    //--></script>
    </body>
    </html>
Hier klicken, um das Bild zu Vergrößern Abbildung 12.3 Die Werte werden aus der Collection ausgelesen und ausgegeben. Sie sehen an diesem Beispiel, dass bereits vorhandene Einträge im Cookie direkt überschrieben werden. Es gibt also keine zwei Einträge namens »Verlag«, sondern beim zweiten Setzen des Eintrags »Verlag« wird der erste Eintrag überschrieben.
<< zurück | <top> | vor >>
Zum Katalog
JavaScript und AJAX bestellen
Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen? Ihre Meinung
Buchtipps
| JavaScript und AJAX - Das Video-Training
| Webseiten programmieren und gestalten
| XHTML, HTML und CSS
| CSS-Praxis
| AJAX
| PHP 5 und MySQL 5
| TYPO3 4.0
Shopping
Versandkostenfrei bestellen in Deutschland und Österreich Info

Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

[Galileo Computing]
Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de