什么是跨域?如何解决跨域问题?
跨域是浏览器的安全机制,阻止不同源之间的请求。解决方案包括 CORS、JSONP、代理服务器和使用 postMessage API。
什么是跨域?
跨域是指浏览器因同源策略而阻止不同源之间的网络请求的行为。当请求的 URL 与当前页面的 URL 在协议(http/https)、域名(如 example.com)或端口(如 8080)中任意一项不同时,就构成跨域。跨域问题本质是浏览器强制实施的安全机制,目的是防止恶意网站窃取或篡改用户敏感数据,例如 Cookie、LocalStorage 或 Ajax 请求。
为什么有跨域限制?
源于同源策略(Same-Origin Policy),这是一种全局性安全限制:
- 约束资源交互:仅允许同源网页脚本访问数据和资源。
- 保护作用:防止跨站脚本攻击(XSS)或数据泄露。 跨域限制仅在浏览器环境中存在,例如 JavaScript 的 Ajax 请求会被拦截。
如何解决跨域问题?
解决思路聚焦于突破浏览器的同源策略限制,常见方法如下:
1. CORS(跨域资源共享)
CORS 是最推荐的方式,需要服务端响应额外头部字段:
- 实现方法:服务端在响应头中添加
Access-Control-Allow-Origin
字段,允许指定源地址访问。// 示例响应头: Access-Control-Allow-Origin: * // 允许所有域 Access-Control-Allow-Methods: GET, POST // 允许多种请求方法 Access-Control-Allow-Headers: Authorization // 允许自定义头部
在服务端支持场景:
- Spring Boot 使用注解
@CrossOrigin
处理特定端点配置。 - Express.js 等通过中间件设置响应头。
2. JSONP(JSON with Padding)
JSONP 利用 <script>
标签加载数据的特性绕过跨域限制:
- 前端实现:动态创建 script 元素,后端返回数据封装于回调函数。
<script> function handleResponse(data) { console.log("Received:", data); } </script> <script src="http://api.example.com/data?callback=handleResponse"></script>
- 后端实现:Node.js 拼接回调函数与数据。
// Node.js 服务器代码示例 const http = require('http'); http.createServer((req, res) => { const callback = req.url.split('callback=').split('&'); const data = JSON.stringify({ status: "success" }); res.end(`${callback}(${data})`); }).listen(3000);
缺点:仅支持 GET 请求。
3. 代理服务器
通过代理将跨域请求中转为本域请求:
- 反向代理 (如 Nginx):Nginx 接受前端请求并访问后端服务。
server { listen 80; server_name localhost; location /api { proxy_pass http://api:9090; proxy_set_header Host $host; } }
- 开发代理 (如 Webpack):在 webpack.config.js 设置开发代理。
module.exports = { devServer: { proxy: { '/api': 'http://localhost:9090' } } };
4. Document.domain + iframe
用于同主域下的子域协作场景:
- 在父页面及 iframe 页面均设置
document.domain
为主域名。document.domain = "example.com"; // 前后端子域需设置一致
确保所有页面均同意域名后实现通信。
5. Nginx 或网关统一配置
服务端直接管理跨域规则,配置网关实现全局放行:
# 示例 (Spring Gateway application.yml):
spring.cloud.gateway.globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "http://localhost:8090"
allowedMethods: "GET, POST"
allowedHeaders: "*"
maxAge: 3600
支持前端域名调用后端服务。
其它补充方法
- PostMessage API:用于窗口间安全跨源数据通信。
- WebSocket 协议:原生支持不同域间的客户端与服务器通讯。
- 禁用浏览器安全策略(仅限开发环境):通过浏览器配置文件临时关闭策略限制。