阿里云主机折上折
  • 微信号
Current Site:Index > The CORS (Cross-Origin Resource Sharing) mechanism

The CORS (Cross-Origin Resource Sharing) mechanism

Author:Chuan Chen 阅读数:40039人阅读 分类: HTML

CORS (Cross-Origin Resource Sharing) Mechanism

Cross-Origin Resource Sharing (CORS) is the core mechanism in modern web development for handling cross-origin requests. It enables secure data interaction between different origins through HTTP header fields, overcoming the limitations imposed by the traditional same-origin policy on cross-origin access.

Same-Origin Policy and Cross-Origin Issues

The same-origin policy is the most fundamental security mechanism in browsers, requiring that scripts can only access resources from the same origin as the current page. The definition of "same origin" requires identical protocol, domain, and port. For example:

  • https://example.com and https://api.example.com are different origins (different subdomains)
  • http://localhost:3000 and http://localhost:8080 are different origins (different ports)
  • https://example.com and http://example.com are different origins (different protocols)

When a frontend attempts to make a cross-origin request, the browser will intercept the response and throw an error. This is particularly common in the development of frontend-backend separated applications.

How CORS Works

CORS enables cross-origin communication by adding specific header fields to HTTP requests and responses. The entire process is divided into two types:

  1. Simple Requests: Meet all the following conditions:
    • Methods are GET, HEAD, or POST
    • Only include safe header fields (Accept, Accept-Language, etc.)
    • Content-Type is application/x-www-form-urlencoded, multipart/form-data, or text/plain
fetch('https://api.example.com/data', {
  method: 'GET',
  headers: {
    'Content-Type': 'text/plain'
  }
});
  1. Preflight Requests: When the conditions for a simple request are not met, the browser first sends an OPTIONS request for preflight:
fetch('https://api.example.com/data', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'X-Custom-Header': 'value'
  },
  body: JSON.stringify({key: 'value'})
});

Server-Side CORS Configuration

The server needs to set the correct response headers to allow cross-origin access. Below are common configuration examples:

Node.js Express Example

const express = require('express');
const app = express();

// Basic CORS configuration
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});

// CORS configuration with credentials
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'https://client.example.com');
  res.header('Access-Control-Allow-Credentials', 'true');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});

// Preflight request handling
app.options('*', (req, res) => {
  res.sendStatus(200);
});

Nginx Configuration Example

location /api/ {
  add_header 'Access-Control-Allow-Origin' '$http_origin';
  add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
  add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
  add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
  
  if ($request_method = 'OPTIONS') {
    add_header 'Access-Control-Max-Age' 1728000;
    add_header 'Content-Type' 'text/plain; charset=utf-8';
    add_header 'Content-Length' 0;
    return 204;
  }
}

Common CORS Header Fields

Header Field Description Example Value
Access-Control-Allow-Origin Allowed origin * or https://example.com
Access-Control-Allow-Methods Allowed HTTP methods GET, POST, PUT
Access-Control-Allow-Headers Allowed request headers Content-Type, Authorization
Access-Control-Allow-Credentials Whether to allow sending credentials true
Access-Control-Expose-Headers Response headers accessible to the client X-Custom-Header
Access-Control-Max-Age Preflight request cache time (seconds) 86400

Credentials and CORS

When requests need to include cookies or HTTP authentication information, credential-related settings must be configured:

// Client-side
fetch('https://api.example.com/user', {
  credentials: 'include'
});

// Server-side response headers
Access-Control-Allow-Origin: https://client.example.com
Access-Control-Allow-Credentials: true

Note: When using credentials, Access-Control-Allow-Origin cannot be the wildcard * and must specify a specific domain.

Common Issues and Solutions

  1. Preflight Request Failure:

    • Ensure the server correctly handles the OPTIONS method
    • Check Access-Control-Allow-Methods and Access-Control-Allow-Headers configurations
  2. Response Headers Not Exposed:

    • Use Access-Control-Expose-Headers to expose custom headers
  3. Caching Issues:

    • Set an appropriate Access-Control-Max-Age to reduce preflight requests
  4. Cross-Origin Cookie Issues:

    • Ensure both withCredentials and Access-Control-Allow-Credentials are set to true
    • Cookies need to have SameSite=None and Secure attributes

Practical Application Scenarios

Cross-Origin API Calls

async function fetchCrossOriginData() {
  try {
    const response = await fetch('https://api.thirdparty.com/data', {
      headers: {
        'Authorization': 'Bearer token123',
        'Content-Type': 'application/json'
      }
    });
    
    if (!response.ok) throw new Error('Network response was not ok');
    
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Fetch error:', error);
  }
}

Cross-Origin Web Fonts

Cross-origin fonts in HTML also require CORS:

<style>
@font-face {
  font-family: 'MyFont';
  src: url('https://cdn.example.com/fonts/myfont.woff2') format('woff2');
  font-display: swap;
}
</style>

The server needs to add CORS headers for font files:

Access-Control-Allow-Origin: *

Security Considerations

  1. Avoid overly permissive CORS policies:

    • Do not use Access-Control-Allow-Origin: * in production
    • Whitelisting is better than wildcards
  2. Protect sensitive operations:

    • Critical APIs should be restricted to specific origins
    • Combine with other security measures like CSRF tokens
  3. Preflight request caching:

    • Set a reasonable Access-Control-Max-Age to balance security and performance

Alternative Solutions Comparison

When CORS is not applicable, consider other cross-origin solutions:

  1. JSONP (GET requests only):
function handleResponse(data) {
  console.log(data);
}

const script = document.createElement('script');
script.src = 'https://api.example.com/data?callback=handleResponse';
document.body.appendChild(script);
  1. Proxy Server:
// Frontend requests same-origin proxy
fetch('/api-proxy/data', {
  method: 'POST',
  body: JSON.stringify({query: 'value'})
});

// Server-side request forwarding
app.post('/api-proxy/data', async (req, res) => {
  const response = await fetch('https://api.example.com/data', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(req.body)
  });
  const data = await response.json();
  res.json(data);
});
  1. WebSocket:
const socket = new WebSocket('wss://api.example.com/ws');
socket.onmessage = (event) => {
  console.log('Message:', event.data);
};

Debugging Tips

  1. Browser Developer Tools:

    • Check CORS-related requests and response headers in the Network panel
    • Pay attention to CORS error messages in the console
  2. Testing Tools:

    • Use cURL to verify server response headers:
    curl -I -X OPTIONS https://api.example.com/data \
    -H "Origin: https://client.example.com" \
    -H "Access-Control-Request-Method: POST"
    
  3. Common Error Message Analysis:

    • No 'Access-Control-Allow-Origin' header: Missing necessary response headers
    • Credentials mode requires 'Access-Control-Allow-Credentials': Credential configuration mismatch
    • Method PUT is not allowed: Method not in the allowed list

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.