Understanding Cross-Origin Resource Sharing (CORS)
Cross-Origin Resource Sharing (CORS) is a browser security mechanism that restricts web pages from making requests to a different domain than the one which served the web page. This restriction prevents malicious scripts on one website from accessing data from another website without permission. Essentially, it’s a gatekeeper for web requests, ensuring that only authorized cross-origin requests are processed.
Imagine you have a web application running on example.com
and you want to fetch data from an API hosted on api.example.net
. Without CORS, the browser would block this request due to the same-origin policy, a fundamental security feature of web browsers. CORS allows the server at api.example.net
to explicitly grant permission for requests originating from example.com
(or other specified origins).
Why is CORS Necessary?
The same-origin policy is a cornerstone of web security. However, modern web applications often need to interact with resources from different domains. CORS provides a standardized way to safely relax the same-origin policy, enabling legitimate cross-origin interactions while still protecting users from malicious attacks.
Implementing CORS with PHP
To enable CORS in your PHP application, you need to set specific HTTP headers in your responses. These headers tell the browser whether or not to allow cross-origin requests.
Here’s a breakdown of the essential CORS headers:
Access-Control-Allow-Origin
: This header specifies the origin(s) that are allowed to access the resource. A value of*
allows requests from any origin, which is suitable for public APIs but should be used with caution in production environments. For greater security, specify a list of allowed origins (e.g.,https://example.com, https://anotherdomain.net
).Access-Control-Allow-Methods
: This header lists the HTTP methods (e.g., GET, POST, PUT, DELETE, OPTIONS) that are allowed for cross-origin requests.Access-Control-Allow-Headers
: This header lists the request headers that are allowed in cross-origin requests. The browser will block requests that include headers not listed here.Access-Control-Allow-Credentials
: When set totrue
, this header indicates that the browser should include credentials (e.g., cookies, authorization headers) in cross-origin requests.Access-Control-Max-Age
: This header specifies the maximum amount of time (in seconds) that the browser can cache the CORS preflight response. This can improve performance by reducing the number of preflight requests.
Handling Preflight Requests (OPTIONS)
Before making a cross-origin request, the browser often sends a "preflight" request using the OPTIONS
method. This request checks if the server allows the cross-origin request. Your PHP application needs to handle these preflight requests by responding with the appropriate CORS headers.
Here’s a complete example of how to implement CORS in your PHP application:
<?php
// Allow from any origin (for development/testing purposes only!)
if (isset($_SERVER["HTTP_ORIGIN"])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
} else {
header("Access-Control-Allow-Origin: *"); //Allow any origin
}
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 600"); // Cache for 10 minutes
// Handle OPTIONS requests (preflight)
if ($_SERVER["REQUEST_METHOD"] == "OPTIONS") {
if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"])) {
header("Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT");
}
if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"])) {
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
}
exit(0); // Exit with a 200 OK status
}
// Your application logic here
$ret = [
'result' => 'OK',
];
header('Content-Type: application/json');
print json_encode($ret);
?>
Explanation:
- Origin Handling: The code checks for the
HTTP_ORIGIN
header and setsAccess-Control-Allow-Origin
accordingly. Using*
allows requests from any origin, which is convenient for development but should be replaced with specific origins in production. - Credentials and Max-Age:
Access-Control-Allow-Credentials
is set totrue
to allow the inclusion of cookies and authorization headers.Access-Control-Max-Age
sets the cache duration for preflight responses. - OPTIONS Handling: The code checks if the request method is
OPTIONS
. If it is, it sets the allowed methods and headers and exits with a 200 OK status. This signals to the browser that the preflight request is successful. - Application Logic: After handling the preflight request, the code executes the application logic and returns the response.
Best Practices for CORS
- Avoid
*
in Production: Always specify the exact origins that are allowed to access your resources. - Restrict Allowed Methods: Only allow the HTTP methods that your API actually supports.
- Limit Allowed Headers: Only allow the request headers that your API needs.
- Use Credentials Wisely: Only enable credentials if your application requires them.
- Validate Input: Always validate any data received from cross-origin requests.
- Keep CORS Configuration Secure: Protect your CORS configuration from unauthorized access.
By implementing CORS correctly and following these best practices, you can enable secure and reliable cross-origin communication in your web applications.