Skip to content

Cross-Origin 策略

跨源(Cross-Origin)策略是浏览器安全模型的核心组成部分,它控制不同源(协议、域名、端口)之间的资源访问和交互。本节将介绍 CORS(跨源资源共享)基础、HTML 中的 crossorigin 属性、以及 COOP(Cross-Origin-Opener-Policy)、COEP(Cross-Origin-Embedder-Policy)和 CORB(Cross-Origin Read Blocking)等高级安全策略。

前置知识

阅读本节前,建议先了解:Permissions Policy

同源策略

浏览器的同源策略(Same-Origin Policy, SOP)限制不同源之间的资源访问:

协议域名端口
Ahttps://example.com443
Bhttps://example.com443
Chttp://example.com443
Dhttps://www.example.com443
Ehttps://example.com8080

CORS 基础

简单请求

服务器通过 Access-Control-Allow-Origin 响应头授权跨域请求:

# 服务器响应头
Access-Control-Allow-Origin: https://trusted.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 3600

预检请求(Preflight)

对于非简单请求(如自定义头、PUT/DELETE 方法),浏览器会先发送 OPTIONS 预检请求:

# 预检请求
OPTIONS /api/data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, X-Custom-Header

# 预检响应
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, PUT, POST, DELETE
Access-Control-Allow-Headers: Content-Type, X-Custom-Header
Access-Control-Max-Age: 3600

HTML crossorigin 属性

script 标签

html
<!-- 不带 crossorigin:不发送凭据 -->
<script src="https://cdn.example.com/lib.js"></script>
<!-- 错误:如果服务器需要 CORS 凭据,会报错 -->

<!-- 带 crossorigin="anonymous":发送不带凭据的跨域请求 -->
<script
  src="https://cdn.example.com/lib.js"
  crossorigin="anonymous"
  integrity="sha384-abc123..."
></script>

<!-- 带 crossorigin="use-credentials":发送带凭据的跨域请求 -->
<script
  src="https://api.example.com/auth.js"
  crossorigin="use-credentials"
></script>

img 标签

html
<!-- 图片默认不发送跨域凭据 -->
<img src="https://cdn.example.com/photo.jpg" alt="照片" />

<!-- 带 crossorigin:可以读取跨域图片的像素数据 -->
<img src="https://cdn.example.com/photo.jpg" crossorigin="anonymous" alt="照片" />

<!-- 使用场景:Canvas 读取跨域图片 -->
<canvas id="canvas"></canvas>
<script>
  const img = new Image();
  img.crossOrigin = 'anonymous';  // 必须设置才能读取像素
  img.src = 'https://cdn.example.com/photo.jpg';
  img.onload = function() {
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0);
    // 可以读取像素数据
    const data = ctx.getImageData(0, 0, canvas.width, canvas.height);
  };
</script>
html
<!-- 字体文件需要 crossorigin 才能正确加载 -->
<link
  rel="preload"
  href="https://fonts.gstatic.com/s/notosanssc.woff2"
  as="font"
  type="font/woff2"
  crossorigin="anonymous"
>

audio/video 标签

html
<!-- 跨域媒体资源 -->
<video
  src="https://video.example.com/stream.m3u8"
  crossorigin="anonymous"
  controls
></video>

<audio
  src="https://audio.example.com/podcast.mp3"
  crossorigin="anonymous"
  controls
></audio>

COOP / COEP / CORB

Cross-Origin-Opener-Policy (COOP)

防止跨域窗口(通过 window.opentarget="_blank")之间的交互:

# 服务器响应头
Cross-Origin-Opener-Policy: same-origin
html
<!-- 启用 COOP 后,跨域打开的窗口无法访问 opener -->
<a href="https://other-site.com" target="_blank" rel="noopener">
  安全打开新窗口
</a>
COOP 值说明
same-origin仅允许同源窗口访问(推荐)
same-origin-allow-popups允许通过 target=_blank 打开的窗口访问
unsafe-none不限制(默认)

Cross-Origin-Embedder-Policy (COEP)

控制页面可以加载哪些跨域资源:

# 服务器响应头
Cross-Origin-Embedder-Policy: require-corp
COEP 值说明
require-corp所有跨域资源需要 CORS 头
credentialless允许无凭据的跨域请求

Cross-Origin-Resource-Policy (CORP)

控制哪些源可以加载当前页面的资源:

# 服务器响应头
Cross-Origin-Resource-Policy: same-origin
CORP 值说明
same-origin仅同源可以加载
same-site仅同站点可以加载
cross-origin所有跨域请求(默认)

CORB (Cross-Origin Read Blocking)

CORB 是浏览器自动保护机制,防止跨域资源被错误地作为敏感类型(HTML/XML/JSON)读取。

完整安全策略示例

# 综合安全响应头
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; frame-ancestors 'none';
Permissions-Policy: camera=(), microphone=(), geolocation=(self), fullscreen=*
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: max-age=31536000; includeSubDomains

注意事项

  1. SRI 需要 crossorigin:使用 integrity 属性时必须设置 crossorigin
  2. Canvas 读取跨域图片需要 crossorigin:否则会报 tainted canvas 错误
  3. COOP/COEP 会影响第三方内容:启用前测试页面功能
  4. CORS 配置在服务器端:HTML 中的 crossorigin 只是客户端设置
  5. **不要使用 Access-Control-Allow-Origin: ***:有安全风险

最佳实践

  • CDN 资源使用 crossorigin="anonymous"
  • SRI 配合 crossorigin 使用
  • 启用 COOP 防止窗口间攻击
  • 根据需要启用 COEP 和 CORP
  • 使用 rel="noopener" 保护 target="_blank" 链接
  • 服务器端正确配置 CORS
  • 使用综合安全策略保护网站

本教程已完成

恭喜你完成了 HTML5 教程的全部学习!建议回顾各章节的核心知识点,结合实战项目巩固所学内容。

参考链接