学无止境

少年辛苦终身事,莫向光阴惰寸功。——唐·杜荀鹤《题弟侄书堂》


什么是跨域及解决办法

1. 跨域基础概念

1.1 什么是跨域

浏览器出于安全考虑,对不同源的请求进行限制,这就是同源策略。

1.2 同源策略要求

  • 协议相同(http/https)
  • 域名相同
  • 端口相同

2. JSONP跨域方案

2.1 基本原理

  • JSONP利用<script>标签不受同源策略限制的特性
  • 通过函数调用的方式包装JSON数据
  • 需要服务端配合返回特定格式的数据

2.2 实现示例


// 客户端实现
function jsonp(url, callback) {
    const script = document.createElement('script');
    script.src = `${url}?callback=${callback}`;
    document.body.appendChild(script);
    
    // 请求完成后删除script标签
    script.onload = function() {
        document.body.removeChild(script);
    };
}

// 服务端实现(Python示例)
def jsonp_view(request):
    callback = request.GET.get('callback')
    data = {'name': 'test', 'value': 123}
    return HttpResponse(f'{callback}({json.dumps(data)})')

2.3 JSONP限制

  1. 只支持GET请求
  2. 需要服务器配合
  3. 错误处理能力有限

3. CORS跨域方案

3.1 基本概念

CORS(Cross-Origin Resource Sharing)是W3C标准的跨域解决方案。

3.2 请求类型

简单请求

满足以下条件的请求:

  1. 请求方法:

    • GET
    • HEAD
    • POST
  2. 允许的Header:


Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type (仅限):
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain

非简单请求

  • 不满足简单请求条件的请求
  • 会触发预检请求(OPTIONS)

3.3 CORS配置

Django配置示例


# settings.py
MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    # ... 其他中间件
]

# 允许所有域名访问
CORS_ALLOW_ALL_ORIGINS = True

# 或指定允许的域名
CORS_ALLOWED_ORIGINS = [
    "https://example.com",
    "https://api.example.com",
]

# 允许的请求方法
CORS_ALLOW_METHODS = [
    'GET',
    'POST',
    'PUT',
    'PATCH',
    'DELETE',
    'OPTIONS'
]

Flask配置示例


from flask_cors import CORS

app = Flask(__name__)
CORS(app, resources={
    r"/api/*": {
        "origins": "*",
        "methods": ["GET", "POST", "PUT", "DELETE"],
        "allow_headers": ["Content-Type"]
    }
})

4. JSONP vs CORS 对比

4.1 功能对比

特性 JSONP CORS
请求方法 仅GET 支持所有HTTP方法
客户端配置 需要 不需要
服务端配置 需要 需要
错误处理 有限 完善
标准化 非标准 W3C标准

4.2 使用建议

  1. 优先使用CORS
  2. 需要兼容旧浏览器时使用JSONP
  3. 简单GET请求可以考虑JSONP

5. 安全考虑

5.1 CORS安全建议

  1. 不要使用Access-Control-Allow-Origin: *
  2. 明确指定允许的域名
  3. 限制必要的HTTP方法
  4. 配置合适的缓存时间

5.2 最佳实践

  1. 使用HTTPS
  2. 实施适当的认证机制
  3. 验证请求来源
  4. 记录跨域请求日志