CORS چیست؟

مشکل CORS چیست؟
اگر شما نیز از توسعه دهندگان وب باشید با مشکلات CORS آشنا شده اید. در صورتی که با این مفهوم آشنا نیستید حتما مطالعه این مقاله را به شما پیشنهاد می کنم. ما در این مقاله مباحث ابتدایی HTTP را توضیح نخواهیم داد بنابراین داشتن درک صحیح و ساده از عملیات های HTTP برای هضم این مقاله لازم است.
زمانی که ما در حال توسعه front-end هستیم در اکثر اوقات داده ای را نمایش می دهیم که جای دیگری (روی سرور دیگری) قرار دارد. به همین منظور مرورگر باید ابتدا یک درخواست HTTP را به سرور مقصد ارسال کند تا تمام داده های مورد نیاز ما را دریافت کند. ما در اینجا نام فرضی www.mywebsite.com را برای وب سایت خود در نظر می گیریم. آدرس API این وب سایت را نیز api.website.com در نظر می گیریم. زمانی که درخواستی به این API ارسال می شود، داده های ما به صورت JSON برای کاربر (هر کسی که درخواست را ارسال کرده است) برگردانده خواهند شد. ما در حال حاضر روی سایت www.mywebsite.com هستیم اما اگر این بار درخواست خود را به دامنه دیگری مانند www.anotherdomain.com ارسال کنیم چه می شود؟ با اجرای این درخواست خطایی به شکل زیر دریافت می کنیم:
Access to fetched has been blocked by CORS policy
CORS مخفف Cross-origin resource sharing یا به اشتراک گذاری منابع از چند سورس مختلف است. برای درک بهتر CORS باید با Same-Origin Policy شروع کنیم.
Same-Origin Policy چیست؟
مرورگرها و دنیای وب به طوری طراحی شده اند که قانونی به نام same-origin policy را اجرا می کنند. این قانون می گوید مقصد درخواست های ما باید با منبعی که به آن هستیم یکی باشد. زمانی مقصد درخواست و منبع آن یکی نیست که:
- به یک دامنه یا زیردامنه دیگر متصل شویم.
- به یک پروتکل دیگر متصل شویم.
- به یک پورت دیگر متصل شویم.
به طور مثال تا زمانی که به وب سایت mywebsite.com متصل باشیم هیچ اشکالی ندارد که به منابع آن دسترسی داشته باشیم (مثلا https://mywebsite.com/image1.png) اما نمی توانیم به منابع وب سایت دیگری مانند anotherdomain.com دسترسی داشته باشیم. این مسئله به سادگی در تصویر زیر مشخص است:

شاید از خودتان بپرسید چرا قانون same-origin وجود دارد؟ فرض کنید هکری لینک مخربی را برای شما ارسال کرده باشد. شما با کلیک روی این لینک به وب سایت هکر منتقل می شوید (مثلا www.evilwebsite.com) که در ظاهر وب سایت بدی نیست اما در پشت صحنه یک iframe از وب سایت بانکی شما (مثلا www.bank.com) باز می شود و هکر با استفاده از کوکی هایی که در مرورگر شما است، شما را وارد حسابتان می کند. طبیعتا این مسئله یک رخنه امنیتی بزرگ است و نباید مجاز باشد. قانون same-origin برای جلوگیری از چنین حملاتی ایجاد شده است و می گوید که دسترسی به resource ها باید از همان origin ای باشد که به آن متصل هستیم. با وجود این قانون وب سایت www.evilwebsite.com نمی تواند به www.bank.com دسترسی داشته باشد.
CORS در سمت کلاینت
منظور ما از سمت کلاینت همان front-end یا مرورگر است. زمانی که وارد دنیای مرورگرها و front-end می شویم باید بدانید که قانون same-origin policy فقط مربوط به اسکریپت ها می شود اما مرورگر ها آن را بسط دادند تا شامل درخواست های جاوا اسکریپتی نیز بشود بنابراین به صورت پیش فرض ما فقط می توانیم به منابعی دسترسی داشته باشیم که از same-origin (از سایتی که در آن هستیم) باشند:

مسئله اینجاست که ما در مواقع بسیاری نیاز به برقراری ارتباط با origin های دیگر (وب سایت های دیگر) داریم. آیا راهی وجود دارد که بر اساس آن بتوانیم به شکل امن از منابع سایت های دیگر نیز استفاده کنیم؟ بله CORS همان راه حل ما است. برایتان توضیح دادم که CORS مخفف Cross-origin resource sharing یا به اشتراک گذاری منابع از چند سورس مختلف است و از همین نام متوجه می شویم که کار آن چیست. User agent ها (مثلا یک مرورگر یا کتابخانه axios یا هر agent دیگری که از آن برای اتصال به یک سایت استفاده شده است) می توانند از مکانیسم خاصی به نام CORS استفاده کنند تا نوع خاصی از درخواست های cross-origin را ارسال کنند. این عملیات با استفاده از تنظیم header های خاصی در درخواست HTTP شما انجام می شود.
زمانی که می خواهیم یک درخواست Cross-origin (درخواستی به منبع دیگر) را ارسال کنیم، مرورگر شما یک header خاص به نام Origin را به درخواست HTTP اضافه می کند. مقدار این header برابر با منبعی است که درخواست از آن ارسال شده است. سرور این درخواست را دریافت کرده و header هایش را بررسی می کند تا بداند هر درخواست از کجا آمده است.
CORS در سمت سرور
اگر شما توسعه دهنده سرور هستید باید header های مجموعه Access-Control را به پاسخ های سرور خود اضافه کنید. مرورگرها بر اساس مقدار این دسته از header ها می توانند مشخص کنند که چه نوع درخواست های cross-origin ای مجاز هستند. در صورتی که Access-Control در header شما نباشد، تمام درخواست های cross-origin بلوکه خواهند شد. تعداد header های مربوط به Access-Control بسیار زیاد است اما مرورگر فقط یک header خاص را برای مجاز دانستن درخواست های cross-origin می خواهد و آن هم Access-Control-Allow-Origin می باشد. مقداری که به این header می دهید مشخص خواهد کرد که چه مقصد هایی می توانند به این منبع (سرور ما) درخواست ارسال کنند. به طور مثال اگر قرار است وب سایت https://mywebsite.com به سرور و وب سایت ما (مثلا https://api.mywebsite.com) دسترسی داشته باشد باید آن را به header ذکر شده پاس بدهیم:

حالا اگر درخواستی از سمت https://mywebsite.com ارسال شود می تواند به منابع موجود در https://api.mywebsite.com نیز دسترسی داشته باشد. از این به بعد مرورگر مقدار موجود در Access-Control-Allow-Origin را با مقصد درخواست شما مقایسه می کند و اگر این دو یکی نباشند اجازه ارسال درخواست را نخواهید داشت. شما می توانید این دو حالت را در دو تصویر زیر مشاهده کنید:


در تصویر دوم خطای معروف CORS را مشاهده می کنیم. قسمت دوم این درخواست دقیقا چیزی که ما توضیح دادیم را ذکر می کند:
The 'Access-Control-Allow-Origin' header has a value 'https://www.mywebsite.com' that is not equal to the supplied origin.
در نظر داشته باشید که Access-Control-Allow-Origin می تواند مقدار * را نیز بگیرد که در این صورت تمام درخواست های CORS از هر منبعی مجاز خواهند بود. انجام این کار پیشنهاد نمی شود چرا که خطرات امنیتی خاص خودش را دارد.
دیدگاهتان را بنویسید