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

שיתוף בטוח של משאבים ממקורות שונים

Mariko Kosaka

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

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

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

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

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

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

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

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

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

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