גלו את סודות ה-CORS (שיתוף משאבים בין מקורות) ולמדו כיצד לאפשר בקשות חוצות-דומיינים באופן מאובטח באפליקציות הרשת שלכם. מדריך מקיף זה מכסה הכל, מהיסודות ועד לתצורות מתקדמות, ומבטיח תקשורת חלקה ומאובטחת בין מקורות שונים.
הסרת המסתורין מ-CORS: מדריך מקיף לשיתוף משאבים בין מקורות
ברשת המקושרת של ימינו, אפליקציות נדרשות לעיתים קרובות לגשת למשאבים ממקורות שונים. כאן נכנס לתמונה מנגנון שיתוף המשאבים בין מקורות (CORS). CORS הוא מנגנון אבטחה חיוני הקובע כיצד דפדפני אינטרנט מטפלים בבקשות ממקור אחד (דומיין, פרוטוקול ופורט) למקור אחר. הבנת CORS חיונית לכל מפתח ווב כדי לבנות יישומי רשת מאובטחים ופונקציונליים.
מהי מדיניות אותו מקור (Same-Origin Policy)?
לפני שצוללים ל-CORS, חשוב להבין את מדיניות אותו מקור (SOP). ה-SOP הוא מנגנון אבטחה בסיסי המיושם בדפדפני אינטרנט. מטרתו היא למנוע מסקריפטים זדוניים באתר אחד לגשת למידע רגיש באתר אחר. מקור מוגדר על ידי השילוב של הפרוטוקול (למשל, HTTP או HTTPS), הדומיין (למשל, example.com), ומספר הפורט (למשל, 80 או 443). שתי כתובות URL נחשבות כבעלות אותו מקור אם הן חולקות את אותו פרוטוקול, דומיין ופורט.
דוגמה:
http://example.com/app1
ו-http://example.com/app2
- אותו מקור (אותו פרוטוקול, דומיין ופורט)https://example.com/app1
ו-http://example.com/app1
- מקור שונה (פרוטוקול שונה)http://example.com:8080/app1
ו-http://example.com/app1
- מקור שונה (פורט שונה)http://sub.example.com/app1
ו-http://example.com/app1
- מקור שונה (תת-דומיין שונה – נחשב לדומיין שונה)
ה-SOP מגביל סקריפטים מגישה למשאבים ממקור שונה, אלא אם כן קיימים אמצעים ספציפיים, כמו CORS, המאפשרים זאת.
מדוע CORS נחוץ?
בעוד שמדיניות אותו מקור חיונית לאבטחה, היא יכולה גם להיות מגבילה. יישומי רשת מודרניים רבים מסתמכים על אחזור נתונים משרתים שונים, כגון ממשקי API או רשתות להעברת תוכן (CDNs). CORS מספק דרך מבוקרת להרפות מה-SOP ולאפשר בקשות לגיטימיות בין מקורות שונים תוך שמירה על אבטחה.
חשבו על תרחיש שבו יישום רשת המתארח ב-http://example.com
צריך לאחזר נתונים משרת API המתארח ב-http://api.example.net
. ללא CORS, הדפדפן היה חוסם בקשה זו בשל ה-SOP. CORS מאפשר לשרת ה-API לציין במפורש אילו מקורות מורשים לגשת למשאביו, ובכך מאפשר ליישום הרשת לתפקד כראוי.
כיצד CORS עובד: היסודות
CORS פועל באמצעות סדרה של כותרות HTTP המוחלפות בין הלקוח (הדפדפן) לשרת. השרת משתמש בכותרות אלו כדי ליידע את הדפדפן האם הוא רשאי לגשת למשאב המבוקש. כותרת ה-HTTP המרכזית המעורבת היא Access-Control-Allow-Origin
.
תרחיש 1: בקשה פשוטה
"בקשה פשוטה" היא בקשת GET, HEAD או POST העומדת בקריטריונים ספציפיים (לדוגמה, כותרת ה-Content-Type
היא אחת מ-application/x-www-form-urlencoded
, multipart/form-data
, או text/plain
). במקרה זה, הדפדפן שולח את הבקשה ישירות לשרת, והשרת משיב עם כותרת Access-Control-Allow-Origin
.
בקשת לקוח (מ-http://example.com):
GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
תגובת שרת (מ-http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"data": "Some data from the server"
}
בדוגמה זו, השרת משיב עם Access-Control-Allow-Origin: http://example.com
, המציין שבקשות מ-http://example.com
מותרות. אם המקור בבקשה אינו תואם לערך בכותרת Access-Control-Allow-Origin
(או אם הכותרת אינה קיימת), הדפדפן יחסום את התגובה וימנע מהסקריפט בצד הלקוח לגשת לנתונים.
תרחיש 2: בקשת Preflight (עבור בקשות מורכבות)
עבור בקשות מורכבות יותר, כגון אלו המשתמשות במתודות HTTP כמו PUT, DELETE, או כאלה עם כותרות מותאמות אישית, הדפדפן מבצע בקשת "preflight" באמצעות מתודת HTTP OPTIONS. בקשת preflight זו מבקשת הרשאה מהשרת לפני שליחת הבקשה האמיתית. השרת משיב עם כותרות המציינות אילו מתודות, כותרות ומקורות מותרים.
בקשת Preflight של הלקוח (מ-http://example.com):
OPTIONS /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
תגובת השרת (מ-http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 3600
הסבר על הכותרות:
Access-Control-Allow-Origin: http://example.com
- מציין שבקשות מ-http://example.com
מותרות.Access-Control-Allow-Methods: GET, PUT, DELETE
- מפרט את מתודות ה-HTTP המותרות לבקשות חוצות-מקור.Access-Control-Allow-Headers: X-Custom-Header, Content-Type
- מפרט את הכותרות המותאמות אישית המותרות בבקשה האמיתית.Access-Control-Max-Age: 3600
- מציין את משך הזמן (בשניות) שבו תגובת ה-preflight יכולה להישמר במטמון הדפדפן. זה עוזר להפחית את מספר בקשות ה-preflight.
אם תגובת ה-preflight של השרת מציינת שהבקשה מותרת, הדפדפן ממשיך עם הבקשה האמיתית. אחרת, הדפדפן חוסם את הבקשה.
הבקשה האמיתית של הלקוח (מ-http://example.com):
PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: some-value
Content-Type: application/json
{
"data": "Some data to be updated"
}
תגובת השרת (מ-http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"status": "Data updated successfully"
}
כותרות CORS נפוצות
להלן פירוט של כותרות ה-CORS המרכזיות שעליכם להכיר:
Access-Control-Allow-Origin
: זוהי הכותרת הבסיסית ביותר. היא מציינת את המקור/ים המורשים לגשת למשאב. ערכים אפשריים כוללים:- מקור ספציפי (למשל,
http://example.com
). *
(תו כללי): זה מאפשר בקשות מכל מקור. יש להשתמש בזהירות, מכיוון שזה עלול לסכן את האבטחה אם מעורב מידע רגיש. בדרך כלל יש להימנע מכך בסביבות ייצור.
- מקור ספציפי (למשל,
Access-Control-Allow-Methods
: כותרת זו מציינת את מתודות ה-HTTP (למשל, GET, POST, PUT, DELETE) המותרות לבקשות חוצות-מקור. היא משמשת בתגובת ה-preflight.Access-Control-Allow-Headers
: כותרת זו מפרטת את הכותרות המותאמות אישית המותרות בבקשות חוצות-מקור. גם היא משמשת בתגובת ה-preflight.Access-Control-Allow-Credentials
: כותרת זו מציינת אם השרת מאפשר לכלול אישורים (credentials) (למשל, עוגיות, כותרות אימות) בבקשות חוצות-מקור. יש להגדיר אותה ל-true
אם אתם צריכים לשלוח אישורים. בצד הלקוח, יש להגדיר גםwithCredentials = true
באובייקט XMLHttpRequest.Access-Control-Expose-Headers
: כברירת מחדל, דפדפנים חושפים רק קבוצה מוגבלת של כותרות תגובה (למשל,Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
) לסקריפטים בצד הלקוח. אם ברצונכם לחשוף כותרות אחרות, עליכם לרשום אותן בכותרתAccess-Control-Expose-Headers
.Access-Control-Max-Age
: כותרת זו מציינת את משך הזמן המרבי (בשניות) שדפדפן יכול לשמור במטמון את בקשת ה-preflight. ערך ארוך יותר מפחית את מספר בקשות ה-preflight ומשפר את הביצועים.
CORS בשפות צד-שרת שונות
יישום CORS כרוך בדרך כלל בקביעת התצורה של יישום צד-השרת שלכם לשליחת כותרות ה-CORS המתאימות. הנה דוגמאות כיצד לעשות זאת בשפות ובמסגרות שונות:
Node.js עם Express
ניתן להשתמש בחבילת המידלוור cors
:
const express = require('express');
const cors = require('cors');
const app = express();
// הפעלת CORS לכל המקורות (יש להשתמש בזהירות בסביבת ייצור)
app.use(cors());
// לחלופין, הגדרת CORS למקורות ספציפיים
// app.use(cors({
// origin: 'http://example.com'
// }));
app.get('/data', (req, res) => {
res.json({ message: 'This is CORS-enabled for all origins!' });
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Python עם Flask
ניתן להשתמש בהרחבת Flask-CORS
:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# לחלופין, הגדרת CORS למקורות ספציפיים
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})
@app.route("/data")
def hello():
return {"message": "This is CORS-enabled for all origins!"}
if __name__ == '__main__':
app.run(debug=True)
Java עם Spring Boot
ניתן להגדיר CORS באפליקציית Spring Boot באמצעות אנוטציות או מחלקות תצורה:
שימוש באנוטציות:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // אפשר בקשות מ-http://example.com
public class DataController {
@GetMapping("/data")
public String getData() {
return "This is CORS-enabled for http://example.com!";
}
}
שימוש בתצורה:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/data")
.allowedOrigins("http://example.com") // אפשר בקשות מ-http://example.com
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
PHP
"This is CORS-enabled for http://example.com!");
echo json_encode($data);
?>
CORS ושיקולי אבטחה
בעוד ש-CORS מאפשר בקשות חוצות-מקור, חיוני ליישם אותו באופן מאובטח. הנה כמה שיקולים חשובים:
- הימנעו משימוש ב-
*
עבורAccess-Control-Allow-Origin
בסביבת ייצור: זה מאפשר בקשות מכל מקור, מה שעלול להוות סיכון אבטחתי. במקום זאת, ציינו במפורש את המקורות המורשים לגשת למשאבים שלכם. - אמתו את כותרת
Origin
בצד השרת: גם אם אתם משתמשים במסגרת שמטפלת בתצורת CORS, זוהי פרקטיקה טובה לאמת את כותרתOrigin
בצד השרת כדי להבטיח שהבקשה מגיעה ממקור צפוי. - שימו לב ל-
Access-Control-Allow-Credentials
: אם אתם משתמשים באישורים (למשל, עוגיות, כותרות אימות), ודאו שאתם מגדיריםAccess-Control-Allow-Credentials: true
בצד השרת ו-withCredentials = true
בצד הלקוח. עם זאת, שימו לב ששימוש ב-Access-Control-Allow-Origin: *
אינו מותר כאשרAccess-Control-Allow-Credentials
מוגדר ל-true
. עליכם לציין במפורש את המקורות המותרים. - הגדירו כראוי את
Access-Control-Allow-Methods
ו-Access-Control-Allow-Headers
: אפשרו רק את מתודות ה-HTTP והכותרות הנחוצות לתפקוד היישום שלכם. זה עוזר להקטין את שטח התקיפה. - השתמשו ב-HTTPS: השתמשו תמיד ב-HTTPS עבור יישומי הרשת וה-API שלכם כדי להגן על נתונים במעבר.
פתרון בעיות CORS
בעיות CORS יכולות להיות מתסכלות לניפוי באגים. הנה כמה בעיות נפוצות וכיצד לפתור אותן:
- "No 'Access-Control-Allow-Origin' header is present on the requested resource": זוהי שגיאת ה-CORS הנפוצה ביותר. משמעותה היא שהשרת אינו שולח את כותרת
Access-Control-Allow-Origin
בתגובתו. בדקו שוב את תצורת צד השרת שלכם כדי לוודא שהכותרת נשלחת כראוי. - "Response to preflight request doesn't pass access control check: It does not have HTTP ok status": שגיאה זו מצביעה על כך שבקשת ה-preflight נכשלה. זה יכול לקרות אם השרת אינו מוגדר לטפל בבקשות OPTIONS או אם כותרות
Access-Control-Allow-Methods
אוAccess-Control-Allow-Headers
אינן מוגדרות כראוי. - "The value of the 'Access-Control-Allow-Origin' header in the response is not equal to the origin in the request": שגיאה זו פירושה שהמקור בבקשה אינו תואם לערך בכותרת
Access-Control-Allow-Origin
. ודאו שהשרת שולח את המקור הנכון בתגובה. - מטמון דפדפן: לפעמים, דפדפנים יכולים לשמור במטמון תגובות CORS, מה שעלול להוביל להתנהגות בלתי צפויה. נסו לנקות את מטמון הדפדפן או להשתמש בדפדפן אחר כדי לראות אם זה פותר את הבעיה. ניתן גם להשתמש בכותרת
Access-Control-Max-Age
כדי לשלוט במשך הזמן שהדפדפן שומר את תגובת ה-preflight.
כלי ניפוי באגים:
- כלי מפתחים בדפדפן: השתמשו בכלי המפתחים של הדפדפן (בדרך כלל נגישים על ידי לחיצה על F12) כדי לבדוק את בקשות ותגובות הרשת. חפשו כותרות והודעות שגיאה הקשורות ל-CORS.
- בודקי CORS מקוונים: ישנם כלים מקוונים שיכולים לעזור לכם לבדוק את תצורת ה-CORS שלכם. כלים אלה שולחים בקשה לשרת שלכם ומנתחים את כותרות התגובה כדי לזהות בעיות פוטנציאליות.
תרחישי CORS מתקדמים
בעוד שמושגי ה-CORS הבסיסיים הם פשוטים יחסית, ישנם כמה תרחישים מתקדמים יותר שיש לקחת בחשבון:
- CORS עם תת-דומיינים: אם אתם צריכים לאפשר בקשות ממספר תת-דומיינים (למשל,
app1.example.com
,app2.example.com
), אינכם יכולים פשוט להשתמש בתו כללי כמו*.example.com
בכותרתAccess-Control-Allow-Origin
. במקום זאת, תצטרכו ליצור באופן דינמי את כותרתAccess-Control-Allow-Origin
על בסיס כותרתOrigin
בבקשה. זכרו לאמת את המקור מול רשימה לבנה של תת-דומיינים מותרים כדי למנוע פרצות אבטחה. - CORS עם מקורות מרובים: אם אתם צריכים לאפשר בקשות ממספר מקורות ספציפיים, אינכם יכולים לציין מספר מקורות בכותרת
Access-Control-Allow-Origin
(למשל,Access-Control-Allow-Origin: http://example.com, http://another.com
אינו חוקי). במקום זאת, תצטרכו ליצור באופן דינמי את כותרתAccess-Control-Allow-Origin
על בסיס כותרתOrigin
בבקשה. - CORS ו-CDNs: בעת שימוש ב-CDN להגשת ה-API שלכם, עליכם להגדיר את ה-CDN להעביר את כותרת
Origin
לשרת המקור שלכם ולשמור במטמון את כותרתAccess-Control-Allow-Origin
כראוי. עיינו בתיעוד של ספק ה-CDN שלכם לקבלת הוראות ספציפיות.
שיטות עבודה מומלצות ל-CORS
כדי להבטיח יישום CORS מאובטח ויעיל, עקבו אחר השיטות המומלצות הבאות:
- עקרון ההרשאה המינימלית: אפשרו רק את הסט המינימלי של מקורות, מתודות וכותרות הנחוצים לתפקוד היישום שלכם.
- בדיקה סדירה של תצורת CORS: ככל שהיישום שלכם מתפתח, בדקו באופן קבוע את תצורת ה-CORS שלכם כדי להבטיח שהיא עדיין מתאימה ומאובטחת.
- השתמשו במסגרת או בספרייה: נצלו מסגרות או ספריות קיימות המספקות תמיכה מובנית ב-CORS. זה יכול לפשט את היישום ולהפחית את הסיכון לשגיאות.
- נטרו הפרות CORS: הטמיעו ניטור כדי לזהות ולהגיב להפרות CORS פוטנציאליות.
- הישארו מעודכנים: התעדכנו במפרטי ה-CORS האחרונים ובהמלצות האבטחה.
סיכום
CORS הוא מנגנון אבטחה קריטי המאפשר בקשות מבוקרות בין מקורות שונים ביישומי רשת. הבנה של אופן פעולת CORS וכיצד להגדיר אותו כראוי חיונית לכל מפתח ווב. על ידי ביצוע ההנחיות והשיטות המומלצות המפורטות במדריך מקיף זה, תוכלו לבנות יישומי רשת מאובטחים ופונקציונליים המתקשרים בצורה חלקה עם משאבים ממקורות שונים.
זכרו תמיד לתעדף את האבטחה ולהימנע משימוש בתצורות CORS מתירניות מדי. על ידי התחשבות זהירה בהשלכות האבטחה של הגדרות ה-CORS שלכם, תוכלו להגן על היישומים והנתונים שלכם מפני גישה לא מורשית.
אנו מקווים שמדריך זה עזר לכם להסיר את המסתורין מ-CORS. קידוד מהנה!