שיתוף משאבים בין מקורות (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, בקשה מורכבת מוגדרת כך:

  • בקשה שמשתמשת בשיטות שאינן 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 כדי לציין את משך הזמן בשניות שבו תוצאות בדיקת הקדם יישמרו במטמון. כך הלקוח יכול לשלוח כמה בקשות מורכבות בלי צורך לחזור על בקשת הקדם-ההפעלה.