A Detailed Explanation of CORS (Cross-Origin Resource Sharing) for Frontend Security

A Detailed Explanation of CORS (Cross-Origin Resource Sharing) for Frontend Security

1. What is CORS?
CORS (Cross-Origin Resource Sharing) is a W3C standard that allows browsers to send XMLHttpRequest or Fetch requests to servers from different origins, overcoming the restrictions of the Same-Origin Policy. Its core mechanism is negotiating cross-origin permissions through HTTP header fields.

2. Why is CORS Needed?

  1. Same-Origin Policy Restrictions: Browsers prohibit cross-origin requests by default, but in practice, frontends often need to access APIs from different domains.
  2. Limitations of Early Solutions: JSONP only supports GET requests and lacks error handling; using a proxy server adds architectural complexity.
  3. Advantages of CORS: Supports all HTTP methods, with controllable security (configured server-side).

3. Two Types of CORS Requests

  1. Simple Request

    • Conditions (all must be met):
      • Method is one of GET, POST, HEAD;
      • Header fields are limited to allowed safe fields (e.g., Accept, Content-Language, Content-Type, etc.);
      • Content-Type is application/x-www-form-urlencoded, multipart/form-data, or text/plain.
    • Process:
      1. The browser directly sends the cross-origin request, automatically adding Origin: https://a.com to the request headers;
      2. The server's response headers must include Access-Control-Allow-Origin: https://a.com (or * to allow any origin);
      3. The browser checks the response headers. If they match, data access is allowed; otherwise, the response is blocked.
  2. Preflight Request

    • Trigger Conditions (any one):
      • Method is a non-simple method like PUT, DELETE, etc.;
      • Contains custom headers (e.g., Authorization);
      • Content-Type is application/json.
    • Process:
      1. The browser first sends an OPTIONS request (preflight request) with headers including:
        Origin: https://a.com  
        Access-Control-Request-Method: PUT  
        Access-Control-Request-Headers: Content-Type,Authorization  
        
      2. The server responds to the preflight request, returning headers such as:
        Access-Control-Allow-Origin: https://a.com  
        Access-Control-Allow-Methods: GET,POST,PUT  
        Access-Control-Allow-Headers: Content-Type,Authorization  
        Access-Control-Max-Age: 86400  // Cache duration for preflight results (seconds)  
        
      3. Only after the preflight is successful does the browser send the actual request, following the same process as a simple request thereafter.

4. Key HTTP Header Fields Explained

Field Name Purpose Example
Origin Declares the origin of the request Origin: https://a.com
Access-Control-Allow-Origin Origins allowed by the server * or https://a.com
Access-Control-Allow-Methods Allowed HTTP methods GET,POST,PUT
Access-Control-Allow-Headers Allowed custom headers Content-Type,Authorization
Access-Control-Allow-Credentials Whether to allow sending cookies true (requires frontend to set withCredentials)
Access-Control-Expose-Headers Response headers accessible to the frontend X-Custom-Header

5. Requests with Credentials
By default, CORS requests do not send cookies. To include credentials:

  1. Frontend setup:
    fetch(url, {  
      credentials: 'include'  // or same-origin  
    });  
    
  2. The server's response headers must satisfy:
    • Access-Control-Allow-Origin cannot be *; it must specify the exact domain;
    • Set Access-Control-Allow-Credentials: true.

6. Common Issues and Solutions

  1. Preflight Request Fails: Check if the server correctly responds to the OPTIONS request and returns allowed Methods and Headers.
  2. Response Blocked: Ensure Access-Control-Allow-Origin matches the Origin, and wildcard * cannot be used when credentials are involved.
  3. Cache Optimization: Use Access-Control-Max-Age to reduce the frequency of preflight requests.

7. Practical Configuration Example (Node.js)

// Middleware to set CORS headers  
app.use((req, res, next) => {  
  res.setHeader('Access-Control-Allow-Origin', 'https://a.com');  
  res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT');  
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization');  
  res.setHeader('Access-Control-Allow-Credentials', 'true');  
  // Directly return 200 for preflight requests  
  if (req.method === 'OPTIONS') {  
    return res.sendStatus(200);  
  }  
  next();  
});  

8. Summary
CORS enables flexible cross-origin communication securely through a mechanism where the server declares permissions and the browser validates them. During development, pay attention to distinguishing between simple and preflight requests, correctly set header fields, and handle requests with credentials carefully.