跨來源資源分享 (CORS) 是一項實作於網路瀏覽器的安全性功能,可允許或限制網頁向與提供網頁服務的網域不同的網域發出要求。
這是一種機制,可啟用受控存取位於特定網域外部的資源。
CORS 對於在不同網路應用程式之間啟用安全通訊,並防止惡意的跨來源要求,至關重要。
透過指定特定標頭,伺服器可指出哪些來源被允許存取其資源,進而維持可用性與安全性之間的平衡。
實作 CORS 支援的良好流程圖:CORS 伺服器流程圖
您可在這裡閱讀規格:https://fetch.spec.whatwg.org/#cors-protocol
對於簡單的 CORS 要求,伺服器只需將下列標頭新增至其回應
Access-Control-Allow-Origin: <domain>, ...
下列程式碼應可啟用延遲 CORS。
$app->options('/{routes:.+}', function ($request, $response, $args) {
return $response;
});
$app->add(function ($request, $handler) {
$response = $handler->handle($request);
return $response
->withHeader('Access-Control-Allow-Origin', 'http://mysite')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
});
選擇性:將下列路由新增為最後的路由
use Slim\Exception\HttpNotFoundException;
/**
* Catch-all route to serve a 404 Not Found page if none of the routes match
* NOTE: make sure this route is defined last
*/
$app->map(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], '/{routes:.+}', function ($request, $response) {
throw new HttpNotFoundException($request);
});
以下是使用 CORS 中間件的完整 CORS 範例應用程式
<?php
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\Factory\AppFactory;
require_once __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->addBodyParsingMiddleware();
// Add the RoutingMiddleware before the CORS middleware
// to ensure routing is performed later
$app->addRoutingMiddleware();
// Add the ErrorMiddleware before the CORS middleware
// to ensure error responses contain all CORS headers.
$app->addErrorMiddleware(true, true, true);
// This CORS middleware will append the response header
// Access-Control-Allow-Methods with all allowed methods
$app->add(function (ServerRequestInterface $request, RequestHandlerInterface $handler) use ($app): ResponseInterface {
if ($request->getMethod() === 'OPTIONS') {
$response = $app->getResponseFactory()->createResponse();
} else {
$response = $handler->handle($request);
}
$response = $response
->withHeader('Access-Control-Allow-Credentials', 'true')
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', '*')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS')
->withHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->withHeader('Pragma', 'no-cache');
if (ob_get_contents()) {
ob_clean();
}
return $response;
});
// Define app routes
$app->get('/', function (ServerRequestInterface $request, ResponseInterface $response) {
$response->getBody()->write('Hello, World!');
return $response;
});
// ...
$app->run();
如果要求包含憑證(Cookie、授權標頭或 TLS 用戶端憑證),您可能需要將 Access-Control-Allow-Credentials
標頭新增至回應物件。
$response = $response->withHeader('Access-Control-Allow-Credentials', 'true');