بررسی Access-Control-Allow-Origin

اغلب اوقات هنگام فراخوانی یک API، ممکن است در کنسول خود خطایی مشاهده کنید که به این صورت است:

 

Access to fetch at 'http://somesite.com' from origin 'http://yoursite.com' has been blocked by CORS policy:
The 'Access-Control-Allow-Origin' header has a value that is not equal to the supplied origin

 

در این پست قصد داریم بدانیم که چرا این خطا رخ می دهد و چگونه می توانید آن را برطرف کنید.

هدر Access-Control-Allow-Origin چیست؟

هدر Access-Control-Allow-Origin جزو هدر‌های CORS است. CORS یا Cross Origin Resource Sharing، مکانیسمی برای مرورگرها است تا به سایتی که در مبدا A در حال کار است اجازه دهد تا منابعی را که در مبدا B هستند را درخواست کند. مبدا (origin) فقط hostname نیست بلکه ترکیبی از پورت و hostname است مانند:

 

http://mysite.example.com:8080

 

مثالی از استفاده‌ از این هدر را بررسی می‌کنیم:

  •  ما origin یا مبدا A را داریم: http://mysite.com و می‌خواهیم از منابع مبدا، B استفاده کنیم: http://yoursite.com
  •  برای حفظ امنیت، مرورگر اجازه‌ی دسترسی به منابع http://yoursite.com را نخواهد‌ داد و درخواست را بلاک می‌کند.
  •  برای این‌که به مبدا A اجازه دسترسی به منابع داده شود، مبدا B باید به مرورگر اطلاع دهد که دریافت منابع از مبدا B اشکالی ندارد.

به کمک CORS، مرورگر‌ها به origin‌ها اجازه می‌دهند تا منابع را بین خود به اشتراک بگذارند.

هدر‌های متعددی وجود دارند که امکان به اشتراک‌گذاری منابع را بین origin‌ها فراهم می‌کنند. اما اصلی‌ترین هدر موجود Access-Control-Allow-Origin است. این هدر به مرورگر اطلاع می‌دهد که origin ها مجاز به دریافت درخواست‌ها از این سرور هستند.

چه کسی باید Access-Control-Allow-Origin را تنظیم کند؟

برای درک اینکه چه کسی باید این هدر را تنظیم کند، این سناریو را در نظر بگیرید: شما در حال جستجوی وب سایتی هستید که برای مشاهده و گوش دادن به آهنگ ها استفاده می شود. این وب سایت سعی دارد در پس زمینه به صورت مخرب ارتباط خود را با بانک شما برقرار کند.

بنابراین چه کسی توانایی نهایی برای جلوگیری از سرقت اطلاعات شما از بانک توسط این وب سایت مخرب را دارد؟ بانک! بنابراین، بانک باید با تنظیم کردن هدر ‘Access-Control-Allow-Origin’ به عنوان بخشی از پاسخ  ، از منابع خود محافظت کند.

بررسی استفاده از هدر در کد

در این قسمت می‌خواهیم یک سرور در origin A، http://localhost:8000، بسازیم که رشته‌ای با محتوای Hello را به API یک نقطه پایانی می‌فرستد. این نقطه پایانی را با ساختن یک کلاینت در origin B، http://localhost:3000، فراخوانی کرده و سپس از fetch برای درخواست منابع استفاده می‌کنیم. انتظار داریم رشته Hello را که توسط origin A منتقل شده است را در کنسول مرورگر origin B ببینیم.

فرض کنیم که ما origin یا منبعی را در http://localhost:8000 داریم که به نقطه‌پایانی /api منابع را ارائه می‌دهد. سرور پاسخ را همراه با هدر Access-Control-Allow-Origin می‌فرستد.

 

const express = require("express");

const app = express();
const port = process.env.SERVER_PORT || 8000;

// Add Access Control Allow Origin headers
app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "https://yoursite.com");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  next();
});

app.get("/api", (req, res) => {
  res.json("Hello");
});

app.listen(port, () => console.log(`Listening on port ${port}`));

 

در سمت کلاینت، میتوانید API را با استفاده از fetch به این صورت فراخوانی کنید:

 

fetch('http://localhost:8000/api')
.then(res => res.json())
.then(res => console.log(res));

 

اکنون درصورتی ‌که کنسول مرورگر خود را باز کنید نتیجه را مشاهده خواهید‌کرد.

از آنجائیکه این هدر در حال حاضر طوری تنظیم شده‌است که فقط اجازه دسترسی از https://yoursite.com را بدهد، مرورگر از دسترسی به منابع جلوگیری کرده و در کنسول، خطای CORS را مشاهده خواهید کرد.

برای حل این مشکل، هدر را به صورت زیر تغییر می‌دهیم:

 

res.setHeader("Access-Control-Allow-Origin", "*");

 

[button class=”github-btn” href=”http://frontcast.ir/course/mern-stack”]دوره جامع MERN Stack[/button]

 

دیدگاه‌ها:

حامد رحیمی

شهریور 27, 1399  در  9:59 ق.ظ

سلام ممنون از آموزشتون
من یک مشکلی و ابهامی دارم
من داخل نود همین کاری که گفتید رو کردم و با قرار دادن علامت ستاره از هر منبعی میتوان به سرور درخواست فرستاد
حالا من میخوام فقط از اون مسیری که وبسایت هست یعنی مثلا کلاینت آدرسش لوکال هاست ۳۰۰۰ هست و من میخوام فقط از این آدرس درخواست قبول کنه.
اینطوری که تنظیم کنیم که ستاره بگذاریم که کلا امنیت سایت و سرور زیر سوال میره درسته؟
پس چاره چیست؟
من همون هدر اول رو که سایت رو مشخص میکنم و مسیر کلاینت رو گذاشتم یعنی اینطوری:
res.setHeader(“Access-Control-Allow-Origin”, “http://127.0.0.1:8000/”);
ولی باز نمیتونم از این مسیر درخواست بفرستم
من برای پروداکشن در اصل این سوال برام هست که چاره چیست؟
ممنون از شما

مسعود صدری

شهریور 27, 1399  در  5:35 ب.ظ

سلام

دقت کنید که Middleware به درستی تعرفی شده باشه و تمام مقدار رو برای Header تنظیم کرده باشید.

app.use((req, res, next) => {
res.setHeader(‘Access-Control-Allow-Origin’, ‘http://localhost:8888’)

res.setHeader(‘Access-Control-Allow-Methods’, ‘GET, POST, DELETE’)

res.setHeader(‘Access-Control-Allow-Headers’, ‘X-Requested-With,content-type’)

res.setHeader(‘Access-Control-Allow-Credentials’, true)

next()
})

افزودن دیدگاه جدید