رازهای CORS (اشتراکگذاری منابع بین مبدأها) را کشف کنید و بیاموزید چگونه درخواستهای بین دامنهای را در برنامههای وب خود به صورت امن فعال کنید. این راهنمای جامع همه چیز را از اصول اولیه تا تنظیمات پیشرفته پوشش میدهد و ارتباطی یکپارچه و امن بین مبدأهای مختلف را تضمین میکند.
ابهامزدایی از CORS: راهنمای جامع اشتراکگذاری منابع بین مبدأها
در وب به هم پیوسته امروزی، برنامهها اغلب نیاز به دسترسی به منابع از مبدأهای مختلف دارند. اینجاست که اشتراکگذاری منابع بین مبدأها (CORS) وارد عمل میشود. CORS یک مکانیزم امنیتی حیاتی است که نحوه مدیریت درخواستهای مرورگرهای وب از یک مبدأ (دامنه، پروتکل و پورت) به مبدأ دیگر را کنترل میکند. درک CORS برای هر توسعهدهنده وب به منظور ساخت برنامههای وب امن و کاربردی ضروری است.
سیاست همان مبدأ (Same-Origin Policy) چیست؟
قبل از پرداختن به CORS، درک سیاست همان مبدأ (SOP) مهم است. SOP یک مکانیزم امنیتی بنیادین است که در مرورگرهای وب پیادهسازی شده است. هدف آن جلوگیری از دسترسی اسکریپتهای مخرب در یک وبسایت به دادههای حساس در وبسایت دیگر است. یک مبدأ با ترکیبی از پروتکل (مثلاً HTTP یا HTTPS)، دامنه (مثلاً example.com) و شماره پورت (مثلاً ۸۰ یا ۴۴۳) تعریف میشود. دو 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ها یا شبکههای تحویل محتوا (CDN)، متکی هستند. CORS روشی کنترلشده برای کاهش محدودیتهای SOP و اجازه دادن به درخواستهای قانونی بین مبدأها با حفظ امنیت فراهم میکند.
سناریویی را در نظر بگیرید که در آن یک برنامه وب میزبانی شده در http://example.com
نیاز به دریافت داده از یک سرور API میزبانی شده در http://api.example.net
دارد. بدون CORS، مرورگر به دلیل SOP این درخواست را مسدود میکند. CORS به سرور API اجازه میدهد تا به صراحت مشخص کند کدام مبدأها مجاز به دسترسی به منابع آن هستند و به این ترتیب برنامه وب را قادر میسازد تا به درستی کار کند.
CORS چگونه کار میکند: اصول اولیه
CORS از طریق مجموعهای از هدرهای HTTP که بین کلاینت (مرورگر) و سرور رد و بدل میشوند، کار میکند. سرور از این هدرها برای اطلاعرسانی به مرورگر در مورد اینکه آیا مجاز به دسترسی به منبع درخواستی است یا خیر، استفاده میکند. هدر HTTP کلیدی درگیر در این فرآیند Access-Control-Allow-Origin
است.
سناریو ۱: درخواست ساده
یک "درخواست ساده" یک درخواست 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
مطابقت نداشته باشد (یا اگر هدر وجود نداشته باشد)، مرورگر پاسخ را مسدود کرده و از دسترسی اسکریپت سمت کلاینت به دادهها جلوگیری میکند.
سناریو ۲: درخواست پیشپرواز (برای درخواستهای پیچیده)
برای درخواستهای پیچیدهتر، مانند آنهایی که از متدهای HTTP مانند PUT، DELETE استفاده میکنند یا دارای هدرهای سفارشی هستند، مرورگر یک درخواست "پیشپرواز" (preflight) با استفاده از متد HTTP OPTIONS انجام میدهد. این درخواست پیشپرواز قبل از ارسال درخواست واقعی، از سرور اجازه میگیرد. سرور با هدرهایی پاسخ میدهد که مشخص میکنند کدام متدها، هدرها و مبدأها مجاز هستند.
درخواست پیشپرواز کلاینت (از 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
- مدت زمانی (بر حسب ثانیه) که پاسخ پیشپرواز میتواند توسط مرورگر کش شود را مشخص میکند. این به کاهش تعداد درخواستهای پیشپرواز کمک میکند.
اگر پاسخ پیشپرواز سرور نشان دهد که درخواست مجاز است، مرورگر به ارسال درخواست واقعی ادامه میدهد. در غیر این صورت، مرورگر درخواست را مسدود میکند.
درخواست واقعی کلاینت (از 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
). *
(wildcard): این مقدار به درخواستها از هر مبدأیی اجازه میدهد. با احتیاط استفاده کنید، زیرا اگر دادههای حساس درگیر باشند، میتواند امنیت را به خطر بیندازد. به طور کلی باید از آن در محیطهای تولیدی اجتناب شود.
- یک مبدأ خاص (مثلاً
Access-Control-Allow-Methods
: این هدر متدهای HTTP (مثلاً GET، POST، PUT، DELETE) مجاز برای درخواستهای بین مبدأ را مشخص میکند. در پاسخ پیشپرواز استفاده میشود.Access-Control-Allow-Headers
: این هدر هدرهای سفارشی مجاز در درخواستهای بین مبدأ را لیست میکند. همچنین در پاسخ پیشپرواز استفاده میشود.Access-Control-Allow-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
: این هدر حداکثر زمانی (بر حسب ثانیه) که یک مرورگر میتواند درخواست پیشپرواز را کش کند را مشخص میکند. مقدار طولانیتر تعداد درخواستهای پیشپرواز را کاهش داده و عملکرد را بهبود میبخشد.
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');
});
پایتون با 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)
جاوا با Spring Boot
شما میتوانید CORS را در برنامه Spring Boot خود با استفاده از انوتیشنها یا کلاسهای پیکربندی، تنظیم کنید:
استفاده از انوتیشنها (Annotations):
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!";
}
}
استفاده از پیکربندی (Configuration):
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 میتواند خستهکننده باشد. در اینجا برخی از مشکلات رایج و نحوه حل آنها آورده شده است:
- "هدر 'Access-Control-Allow-Origin' در منبع درخواستی وجود ندارد": این رایجترین خطای CORS است. به این معنی است که سرور هدر
Access-Control-Allow-Origin
را در پاسخ خود ارسال نمیکند. پیکربندی سمت سرور خود را دوباره بررسی کنید تا مطمئن شوید که هدر به درستی ارسال میشود. - "پاسخ به درخواست پیشپرواز بررسی کنترل دسترسی را پاس نمیکند: وضعیت HTTP ok ندارد": این خطا نشان میدهد که درخواست پیشپرواز ناموفق بوده است. این میتواند در صورتی رخ دهد که سرور برای مدیریت درخواستهای OPTIONS پیکربندی نشده باشد یا هدرهای
Access-Control-Allow-Methods
یاAccess-Control-Allow-Headers
به درستی پیکربندی نشده باشند. - "مقدار هدر 'Access-Control-Allow-Origin' در پاسخ با مبدأ موجود در درخواست برابر نیست": این خطا به این معنی است که مبدأ موجود در درخواست با مقدار هدر
Access-Control-Allow-Origin
مطابقت ندارد. مطمئن شوید که سرور مبدأ صحیح را در پاسخ ارسال میکند. - کش کردن مرورگر: گاهی اوقات، مرورگرها میتوانند پاسخهای CORS را کش کنند که میتواند منجر به رفتار غیرمنتظره شود. سعی کنید کش مرورگر خود را پاک کنید یا از مرورگر دیگری استفاده کنید تا ببینید آیا مشکل برطرف میشود یا خیر. همچنین میتوانید از هدر
Access-Control-Max-Age
برای کنترل مدت زمان کش شدن پاسخ پیشپرواز توسط مرورگر استفاده کنید.
ابزارهای عیبیابی:
- ابزارهای توسعهدهنده مرورگر: از ابزارهای توسعهدهنده مرورگر (معمولاً با فشردن 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 و CDNها: هنگام استفاده از CDN برای ارائه API خود، باید CDN را طوری پیکربندی کنید که هدر
Origin
را به سرور مبدأ شما ارسال کند و هدرAccess-Control-Allow-Origin
را به درستی کش کند. برای دستورالعملهای خاص، با مستندات ارائهدهنده CDN خود مشورت کنید.
بهترین شیوههای CORS
برای اطمینان از پیادهسازی امن و کارآمد CORS، این بهترین شیوهها را دنبال کنید:
- اصل کمترین امتیاز: فقط به حداقل مجموعه مبدأها، متدها و هدرهایی که برای عملکرد صحیح برنامه شما ضروری هستند، اجازه دهید.
- پیکربندی CORS را به طور منظم بازبینی کنید: با تکامل برنامه شما، به طور منظم پیکربندی CORS خود را بازبینی کنید تا اطمینان حاصل شود که هنوز مناسب و امن است.
- از یک فریمورک یا کتابخانه استفاده کنید: از فریمورکها یا کتابخانههای موجود که پشتیبانی داخلی از CORS را ارائه میدهند، استفاده کنید. این کار میتواند پیادهسازی را ساده کرده و خطر خطا را کاهش دهد.
- نقضهای CORS را نظارت کنید: نظارتی را برای شناسایی و پاسخ به نقضهای احتمالی CORS پیادهسازی کنید.
- بهروز بمانید: با آخرین مشخصات و توصیههای امنیتی CORS بهروز باشید.
نتیجهگیری
CORS یک مکانیزم امنیتی حیاتی است که درخواستهای کنترلشده بین مبدأ را در برنامههای وب امکانپذیر میسازد. درک نحوه کار CORS و نحوه پیکربندی صحیح آن برای هر توسعهدهنده وب ضروری است. با پیروی از دستورالعملها و بهترین شیوههای ذکر شده در این راهنمای جامع، میتوانید برنامههای وب امن و کاربردی بسازید که به طور یکپارچه با منابع از مبدأهای مختلف تعامل دارند.
به یاد داشته باشید که همیشه امنیت را در اولویت قرار دهید و از استفاده از پیکربندیهای CORS بیش از حد مجاز خودداری کنید. با در نظر گرفتن دقیق پیامدهای امنیتی تنظیمات CORS خود، میتوانید از برنامهها و دادههای خود در برابر دسترسی غیرمجاز محافظت کنید.
امیدواریم این راهنما به شما در ابهامزدایی از CORS کمک کرده باشد. کدنویسی خوش!