[עמוד ראשי]   [נושא קודם]
Cookies - "עוגיות"


1. כללי
אובייקט ה- Document מכיל תכונה בשם cookie (עוגיה), תכונה זו הינה מחרוזת השולטת במאפיין חשוב מאד של דפדפן הרשת.
טיפ :
השם cookie אינו בעל משמעות מירבית וחשובה, אך ישנו תקדים לשם זה. בתולדות המעורפלות של הסטורית המחשבים,
המושג cookie או "magic cookie" (עוגיית מזל) שימש כהתייחסות לפיסת מידע קטנה, במיוחד עבור מידע סודי או מיוחד / מיוחס, דומה לסיסמא, המוכיחה זהות או הרשאת גישה.
ב- cookie JS משמשת על מנת לשמור מצב ויכולה לשרת / לשמש כסוג של זהות עבור דפדפן הרשת.
cookie איננה משתמשת בכתבי סתרים ואינה בטיחותית בשום דרך / צורה.
cookie היא בעצם כמות של מידע שמי המאוחסן על ידי דפדפן הרשת ומקושר לדף רשת / אתר ספציפי ברשת.
cookie משמשת על מנת לתת לדפדפן הרשת זכרון, כך שיוכל להשתמש במידע, שהיווה קלט בדף אחד עבור דף אחר ברשת או על מנת לאחזר עדיפות / חיבה מיוחדת או משתני מצב כאשר המשתמש עוזב דף ברשת וחוזר אליו.

Cookie עוצבה במקור עבור טכנולוגיית CGI וברמה הנמוכה מיושמת כהרחבה לפרוטוקול HTTP שזה (Hyper Transmit Transfer Protocol).
מידע של cookie מועבר באופן אוטומטי בין דפדפני רשת ושרתי רשת כך שסקריפטים של CGI בשרת יכולים לקרא ולכתוב את ערכי ה- cookie אשר מאוחסנים בצד "הלקוח". cookie היא תכונה, מחרוזת אשר מאפשרת לקרא, ליצור, לשנות ולמחוק את ה- cookie או cookies אשר מתייחסות לדף הרשת הנוכחי.
כאשר נקרא הערך המאוחסן ב- cookie, נקבל מחרוזת אשר מכילה את השמות והערכים של ה- cookies המיושמות במסמך (document) זה. אנו יוצרים, משנים או מוחקים cookie על ידי הצבה / שינוי הערך של התכונה.

כיצד עובדות cookies

כל cookie היא בעלת ארבע תכונות אופציונליות, אשר שולטות באורך החיים, הראות והבטיחות שלה.
א.   התכונה הראשונה היא expires (להסתיים, למות), אשר מתארת את אורך חיי ה- cookie. cookies, הן ארעיות, הערכים שהן מאחסנות כברירת מחדל הם שהן קיימות כל עוד קיים ה- session של דפדפן הרשת.
אם נרצה ש- cookie תמשך מעבר לזמן קיומו של session, נשתמש בתכונת ה- expires על מנת לציין זמן סיום. זה גורם לדפדפן לשמור את ה- cookie בקובץ מקומי, על מנת שיוכל לקרא אותו חזרה בפעם הבאה שהמשתמש יבקר באותו הדף ברשת. כאשר פג התוקף, ה- cookie נמחקת באופן אוטומטי מהקובץ.

ב.   התכונה השניה היא path, אשר מתארת את דפי הרשת שאליהם מקושרת ה- cookie. כברירת מחדל cookie מקושרת ונגישה לדפי רשת אשר יצרו אותה ולכל דפי הרשת האחרים הנמצאים באותה הספריה או בתתי ספריות של אותה הספריה.
לדוגמא: אם הדף http://www.biu.ac.il/courses/menu.htm יוצר cookie, לדוגמא, cookie זו נגישה ו נראית גם לדפים http://www.biu.ac.il/courses/new.html ו- http://www.biu.ac.il/courses/math/menu.htm אך אינה נגישה לדף http://www.biu.ac.il/menu.htm .
התנהגות זו היא בדרך כלל בדיוק מה שאנו צריכים / רוצים, אך לפעמים נרצה להשתמש בערכי cookie מסויימת עבור מספר רב של דפי אתר ברשת, ללא כל קשר מיהו הדף שיצר את ה- cookie. על מנת לאשר זאת, נציין path (שביל) ל- cookie, כך כל דף ברשת מאותו שרת המכיל את ה- path הזה, בכתובת URL שלו יוכל לחלוק ב- cookie,
לדוגמא:
אם cookie מצויינת על ידי ה-path http://www.acme.com/catalog/widgets/menu.htm וה-path מאותחל ל- cookie ,"/catalog" זו נראית גם ל- http://www.acme.com/catalog/menu.htm או אם ה- path מאותחל ל- "/" , ה- cookie נראית לכל דף בשרת www.acme.com .
כברירת מחדל, cookies נגישות אך ורק לדפים של אותו השרת ממנו נוצרו. אתרים גדולים, ודאי ירצו כי cookies יהיו משותפות עבור כמה שרתים,
לדוגמא, השרת order.acme.com יצטרך לקרוא את ערכי ה- cookie שהוכנסו ב- catalog.acme.com . כאן נכנסת התכונה השלישית של cookie.

ג.   Domain – אם cookie נוצרה בדף catalog.acme.com נאתחל את ה- path שלו ל- "/" ואת ה domain - שלו ל- "acme.com".
cookie זו תהייה נגישה לכל דפי הרשת ב- catalog.acme.com וב- orders.acme.com או לכל שרת אחר ב-domain של acme.com כאשר תכונה זו אינה מאותחלת, ברירת המחדל היא ה"מארח" (hostname) של אותו שרת, המספק את הדפים. לא ניתן לאתחל את הdomain - לאחד אחר מלבד זה של השרת שלו.

ד.   התכונה הרביעית והאחרונה היא בעלת ערך בוליאני בשם secure, אשר מציינת כיצד ערכי cookie מועברים ברשת.
כברירת מחדל, cookies אינן מאובטחות, משמע, הן מועברות דרך קשר בלתי מאובטח של פרוטוקול HTTP. אם cookie מסומנת כ- secure היא מועברת אך ורק כאשר הדפדפן והשרת מחוברים דרך HTTPS או פרוטוקול מאובטח אחר.

4 תכונות אלו אינן תכונות של אובייקטי JS.
ניתן למצוא פרטים טכניים מלאים לגבי cookies בכתובת : http://www.netscape.com/newsref/std/cookie_spec.html.
מסמך זה הוא המפרט הרשמי עבור cookies ב- HTTP, הוא מכיל פרטים אשר רלוונטיים יותר לטכנולוגיית CGI מאשר לתכנות ב- JS.
2. אחסון
על מנת לקשר ערך של cookie ארעית עם המסמך הנוכחי פשוט נאתחל את תכונת ה- cookie למחרוזת בפורמט: ;ערך = שם (name = value;) , דוגמה:
document.cookie = "version=" + escape(document.lastModified);
בפעם הבאה בה נקרא את תכונת ה- cookie, הזוג שם – ערך שאוחסנו יכלל ברשימת ה- cookies של המסמך.
ערכי cookies אינם כוללים סימנים כמו נקודה-פסיק, פסיקים, או רווחים. מסיבה זו נרצה להשתמש בפונקציה ( )escape של JS, על מנת להצפין את הערך טרם איחסונו ב- cookie. אם נעשה זאת, נצטרך להשתמש בפונקציה המקבילה ( )unescape כאשר נקרא את ערך ה- cookie.
על מנת לשנות את אורך חייה של ה- cookie נשתמש בתכונה expires כך :
name = value; expires = date;
התאריך צריך להיות נקוב בפורמט Date.toGMTString( ). דוגמא, על מנת לייצר cookie שאורך חייה הוא שנה, נשתמש בקוד הבא :
var nextyear = new Date();
nextyear.setFullYear(nextyear.getFullYear();
document.cookie = "version=" + document.lastModified + "; expires=" + nextyear.toGMTString();
    
באופן דומה, נאתחל את התכונות path, domain, secure על ידי צירוף של מחרוזות בצורה הבאה, לפני שערך זה נכנס לתכונות ה- cookie :
path = path ;
domain = domain ;
secure ;
    
על מנת למחוק cookie, נאתחל אותה שוב כאשר נשתמש באותו השם, בערך שרירותי ותאריך תפוגה (אורך חיים) שכבר עבר. נשים לב כי הדפדפן אינו נדרש למחוק את ה- cookies שפג תוקפן באופן מיידי, על כן, ייתכן כי cookie שפג תוקפה עדיין קיימת בקובץ ה- cookies של הדפדפן.

הגבלות / מגבלות ה- cookie

cookies מכוונות לאחסון בלתי תדיר של כמות מידע קטנה. הן אינן מיועדות למטרת תקשורת ואינן משמשות כמנגנון העברת מידע, על כן, עלינו להשתמש בהן במתינות. דפדפני רשת אינם נדרשים להחזיק ביותר מסך הכל 300 cookies או לא יותר מ 20- עבור שרת רשת (עבור כל השרת, לא רק עבור הדף שלנו או אתר בשרת), או לא להחזיק ביותר מ -4 קילובייט של מידע עבור cookie ספציפית (השם והערך נספרים יחדיו לקראת גבול זה).
המגבלה הגדולה ביותר היא ההגבלה של 20 cookies עבור שרת, כך שזה אינו רעיון טוב להשתמש ב- cookie נפרדת עבור כל משתנה שאנו מעוניינים לשמור. במקום, עלינו לנסות לאחסן מספר משתני מצב בתוך cookie בעלת שם אחד.
3. קריאה
כאשר אנו משתמשים בתכונת ה- cookie בביטוי JS, הערך המוחזר הוא מחרוזת המכילה את כל ה- cookies שקשורות במסמך הנוכחי. המחרוזת הינה רשימה של זוגות, שמות וערכיהם אשר מופרדים בסימן נקודה-פסיק. הערך אינו מכיל אף אחת מ- 4 התכונות של ה- cookie.
על מנת לקבוע את הערך של ה- cookie על פי השם, נוכל להשתמש במתודות String.indexOf( ) , String.substring( ) ו- String.split( ). לאחר ש"חילצנו" את ערך ה- cookie עלינו לתרגם את הערך, בהתבסס על הפורמט בו השתמשו כאשר הצפינו את המידע ביצירת ה- cookie.
var allcookies = document.cookie;       // cookie קריאת תכונת ה
var pos = allcookies.indexOf("vers=");  // "vers" אשר שמה cookie חיפוש ה 

// חילוצה ואחר כך שימוש בערכה אם מצאנו כזו
if( pos != -1)
  var start = pos + 8; 
var end = allcookies.indexOf(";", start);
if ( end == -1)
  end = allcookies.length;
var value = allcookies.sustring(start, end); 
value = unescape(value);
if (value != document.lastModified)
  alert("This document has changed since you were last here");
    
נשים לב כי את 4 התכונות של ה- cookie הנ"ל, ניתן רק לאתחל אך לא ניתן לקרא אותן.
4. דוגמא
דוגמא אשר לוקחת בחשבון את כל ההיבטים שהוזכרו בנושאי cookies.
ראשית, הדוגמא מגדירה Cookie class. כאשר אנו יוצרים אובייקט מסוג Cookie, אנו מפרטים אובייקט Document, שם עבור ה- cookie וכאופציה, תאריך תפוגה, path, domain וערך בוליאני עבור secure.
לאחר יצירת אובייקט מסוג Cookie, ניתן לאתחל מחרוזת תכונות שרירותיות עבור אובייקט זה. הערכים עבור תכונות אלו הם הערכים אשר מאוחסנים ב- cookie.
מחלקת ה- Cookie מגדירה 3 מתודות:

מתודה ( )store עוברת בלולאה על כל התכונות שהוגדרו על ידי המשתמש עבור אובייקט ה- Cookie ומשרשרת את שמותיהם וערכיהם לתוך מחרוזת אחת.

מתודה ( )load קוראת את תכונות ה- cookie של אובייקט ה- Document על מנת לקבל את ערכיהם של כל ה- cookies עבור מסמך זה. היא מחפשת במחרוזת על מנת למצוא את הערך עבור ה- Cookie בעל השם הספציפי ואז מחלקת את הערך לשמות וערכים בודדים.

מתודה ( )remove מוחקת את ה- cookie הנקובה מהמסמך.

פונקצית ה- constructor : יוצרת אובייקט מסוג Cookie עבור המסמך המתואר בעל השם המתואר ובעל תכונות אופציונליות.
ארגומנטים :
document : אובייקט ה- Documentשעבורו מאוחסנת ה-cookie.
name : מחרוזת המהווה את שם ה- cookie (חובה).
hours : מספר שעות חיי ה-cookie מרגע יצירתה (אופציונלי).
path : מחרוזת המהווה את הנתיב של ה-cookie (אופציונלי).
domain : מחרוזת המהווה את הdomain- של ה- cookie (אופציונלי).
secure : משתנה בעל ערך בוליאני, כאשר הינו בעל ערך "אמת" דורש cookie מוגנת (אופציונלי).
<script language="JavaScript1.1">

  function Cookie(document,name,hours,path,domain,secure)
  {
    // כל התכונות של אובייקט זה, המוגדרות מראש מתחילות בסימן '$' על מנת להבחין אותם מתכונות
    //cookie - אחרות אשר מהוות את הערכים שיאוחסנו ב   
    this.$document = document;
    this.$name = name;
    if(hours)
      this.$expiration = new Date(( new Date()).getTime() + hours * 3600000);
    else
      this.$expiration = null;
    if(path)
      this.$path = path;
    else 
      this.$path = null;
    if(domain)
      this.$domain = domain;
    else 
      this.$domain = null;
    if(secure)
      this.$secure = secure;
    else 
      this.$secure = null;
  }
  
  function cookieStore()
  {
    // ומקבצת יחד את הערכים Cookie עוברת בלולאה על התכונות של אובייקט ה store() - פונקציית ה 
    for(var prop in this)
    {
      if(( prop.charAt(0) == '$') || ((typeof this[prop] == 'function'))
        continue;
      if( cookieval != "")
        cookieval +='&';
      cookieval + prop + ':' + escape (this[prop]);
    }
    
    // , נאחד אותם למחרוזת הכוללת את השם ואת התכונות הנוספות cookie כעת, משיש לנו את ערכי ה
    // שתוארו קודם ונוצרו בזמן יצירתה 
    var cookie = this.$name + '=' + cookieval;
    if(this.$expiration)
      cookie += '; expires=' + this.$expiration.toGMTString();
    if(this.$path ) 
      cookie += '; path=' + this.$path;
    if(this.$domain) 
      cookie += '; domain' + this.$domain;
    if(this.$secure) 
      cookie += '; secure';
    this.document.cookie = cookie;
  }
  
  function cookieLoad()
  {
    // השייכות לטופס זה cookies יצירת רשימה של כל ה 
    var allCookies = this.$document.cookie;
    if (allCookies == "") 
      return false;
      
    // הרצויה מן הרשימה cookie כעת נחלץ רק את ה 
    var start = allCookies.indexOf(this.$name + '=');
    if (start == -1)
      return false;
    start += this.$name.length + 1;
    var end = allCookies.indexOf(':',start);
    if(end == -1)
      end = allCookies.length;
    var cookieval = allCookies.substring(start,end); 
    
    // & זוגות השם-ערך המופרדים בסימן cookie כעת עלינו להפריד את משתני המצב השונים שמכילה ה
    // על מנת להפריד את כולם split() והשמות-ערכים מופרדים על יד הסימן : נשתמש בפונקציה
    var cookieval.split('&');
    for(var i=0; i < a.length ; i++)
      a[i] = a[i].split(':');
      
    // unescape() בערכים אלו. נשים לב כי אנו משתמשים בפונקציה Cookie כעת נאתחל את אובייקט ה
    // כאשר אחסנו אותם escape() עבור ערכי התכונות, משום שהשתמשנו בפונקציה
    for (var i=0; i < a.length; i++)
      this[a[i][0]] = unescape(a[i][1]);
    return true;
  }
  
  function cookieRemove()
  {
    var cookie;
    cookie = this.$name + '=';
    if(this.$path ) 
      cookie += '; path=' + this.$path;
    if(this.$domain) 
      cookie += '; domain' + this.$domain;
    cookie += '; expires=Fri , 03-MAY-2002 00:00:00 GMT';
    this.$document.cookie = cookie;
  } 
   
  // על מנת להפוך את prototype דמה על מנת שנוכל להשתמש באובייקט ה Cookie יצירת אובייקט
  // הפונקציות הנ"ל למתודות
  new Cookie();
  Cookie.prototype.store = cookieStore;
  Cookie.prototype.load = cookieLoad;
  Cookie.prototype.remove = cookieRemove
    
הקוד הבא הינו דוגמא לשימוש ב- Cookie Class :

cookie זו תהיה נגישה מכל דפי הרשת הקיימים באותה התיקיה או הקיימים בתיקיות שנמצאות מעליה ב"עץ" (מכיוון שאנו משתמשים ב- path של ברירת המחדל), ולכן אנו רוצים שתהיה בעלת שם ייחודי. אורך החיים שניתן לה בדוגמא זו הוא 10 ימים.
var visitorData = new Cookie(document, "name_color_count_state", 240);
נסיון קריאה של מידע המאוחסן ב- cookie, במידה ומידע זה אינו קיים, בקשה מהמשתמש למידע זה.
if(!visitorData.load() || !visitorData.name || !visitorData.color)
{
  visitorData.name = prompt("What is your name ? : ", "");
  visitorData.color = prompt("What is your favorite color ? :", "");
}
    
עדכון המידע לגבי מספר הפעמים בהם ביקר המשתמש בדף רשת זה :
if(visitorData.visits == null)
  visitorData.visits = 0;
visitorData.visits++;
visitorData.store();
    
כעת נוכל להשתמש במשתני המצב שאנו קוראים :
  document.write('<FONT SIZE=7 COLOR="' + visitorData.color + '">' +
      'Welcome, ' + visitorData.name + '!' + '<FONT>' +
      '<P> You have visited ' + visitorData.visits + ' times .');
</SCRIPT>
</FORM>
  <INPUT TYPE="button" VALUE="Forget My Name" onClick="visitorData.remove();">
</FORM>