שיתוף משאבים בין מקורות (CORS)

שיתוף משאבים בין מקורות בצורה בטוחה

Mariko Kosaka

מדיניות המקור הזהה של הדפדפן חוסמת קריאת משאב ממקור אחר. המנגנון הזה מונע מאתרים זדוניים לקרוא נתונים של אתרים אחרים, אבל הוא גם מונע שימושים לגיטימיים.

אפליקציות אינטרנט מודרניות לרוב רוצות לקבל משאבים ממקור אחר, למשל אחזור נתוני JSON מדומיין אחר או טעינת תמונות מאתר אחר לרכיב <canvas>. אלה יכולים להיות משאבים ציבוריים שצריכים להיות זמינים לקריאה לכולם, אבל מדיניות המקור הזהה חוסמת את השימוש בהם. בעבר, מפתחים השתמשו בפתרונות זמניים כמו JSONP.

שיתוף משאבים בין מקורות (CORS) פותר את הבעיה הזו בדרך סטנדרטית. הפעלת CORS מאפשרת לשרת לומר לדפדפן שהוא יכול להשתמש במקור נוסף.

איך פועלת בקשה לשימוש במשאבים באינטרנט?

בקשה ותגובה
איור של בקשת לקוח ותגובת שרת.

דפדפן ושרת יכולים להחליף נתונים ברשת באמצעות Hypertext Transfer Protocol‏ (HTTP). ב-HTTP מוגדרות כללי התקשורת בין מבצע הבקשה לבין מי שמשיב, כולל המידע הנדרש כדי לקבל משאב.

כותרת ה-HTTP מאפשרת לנהל משא ומתן על החלפת ההודעות בין הלקוח לשרת, ומשמשת לקביעת הגישה. גם הבקשה מהדפדפן וגם הודעת התגובה מהשרת מחולקות לכותרת ולגוף.

מידע על ההודעה, כמו סוג ההודעה או הקידוד שלה. הכותרת יכולה לכלול מגוון מידע שמבוטא כצמדי מפתח/ערך. כותרת הבקשה וכותרת התשובה מכילות מידע שונה.

כותרת בקשה לדוגמה

Accept: text/html
Cookie: Version=1

הכותרת הזו זהה למשפט "אני רוצה לקבל HTML בתגובה. זה קובץ cookie שיש לי".

דוגמה לכותרת תשובה

Content-Encoding: gzip
Cache-Control: no-store

הכותרת הזאת מקבילה למילים "הנתונים בתגובה הזו מקודדים באמצעות gzip. אין לשמור במטמון".

גוף

ההודעה עצמה. זה יכול להיות טקסט רגיל, קובץ תמונה בינארי, קובץ JSON, קובץ HTML או פורמטים רבים אחרים.

איך פועל CORS

מדיניות המקור הזהה מנחה את הדפדפן לחסום בקשות ממקורות שונים. כשצריך משאב ציבורי ממקור אחר, השרת שמספק את המשאבים מורה לדפדפן שהמקור ששולח את הבקשה יכול לגשת למשאב שלו. הדפדפן זוכר את זה ומאפשר שיתוף משאבים בין מקורות למשאב הזה.

שלב 1: בקשה מהלקוח (הדפדפן)

כשהדפדפן שולח בקשה ממקורות שונים, הוא מוסיף כותרת Origin עם המקור הנוכחי (הסכימה, המארח והיציאה).

שלב 2: תגובת השרת

כששרת רואה את הכותרת הזו, והוא רוצה לאפשר גישה, הוא מוסיף כותרת Access-Control-Allow-Origin לתגובה עם ציון המקור של מבצע הבקשה (או * כדי לאפשר גישה לכל מקור).

שלב 3: הדפדפן מקבל תשובה

כשהדפדפן רואה את התשובה הזו עם כותרת Access-Control-Allow-Origin מתאימה, הוא משתף את נתוני התשובה עם אתר הלקוח.

שיתוף פרטי כניסה באמצעות CORS

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

בקשה

מוסיפים credentials: 'include' לאפשרויות האחזור, כמו בדוגמה הבאה. הבקשה כוללת את קובץ ה-cookie באופן הבא:

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})

תשובה

צריך להגדיר את Access-Control-Allow-Origin למקור ספציפי (ללא תו כללי לחיפוש באמצעות *) ולהגדיר את Access-Control-Allow-Credentials לערך true.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

בקשות קדם-הפעלה לקריאות HTTP מורכבות

כשאפליקציית אינטרנט שולחת בקשת HTTP מורכבת, הדפדפן מוסיף בקשה לפני הטיסה לתחילת שרשרת הבקשות.

במפרט CORS מוגדרת בקשה מורכבת באופן הבא:

  • בקשה שמשתמשת ב-methods שאינן GET, POST או HEAD.
  • בקשה שכוללת כותרות שאינן Accept,‏ Accept-Language או Content-Language.
  • בקשה עם כותרת Content-Type שאינה application/x-www-form-urlencoded, multipart/form-data או text/plain.

הדפדפנים יוצרים באופן אוטומטי את כל הבקשות הנדרשות לקדם-הפעלה ושולחים אותן לפני הודעת הבקשה בפועל. בקשת קדם-ההפעלה היא בקשת OPTIONS כמו הדוגמה הבאה:

OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE

בצד השרת, האפליקציה שמקבלת את הבקשה מגיבה לבקשת ההכנה מראש עם מידע על השיטות שהאפליקציה מקבלת מהמקור הזה:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS

תגובת השרת יכולה לכלול גם כותרת Access-Control-Max-Age כדי לציין את משך הזמן בשניות שבו תוצאות בדיקת הקדם יישמרו במטמון. כך הלקוח יכול לשלוח מספר בקשות מורכבות בלי לחזור על בקשת הקדם-ההפעלה.