跨域问题理解
前端跨域处理是解决前端开发过程中由于浏览器的同源策略,而无法直接访问不同源(协议、域名、端口)的资源的问题。
浏览器接收跨域请求时,报错如下:
跨域问题解决
本地配置解决跨域
这些配置均注意在开发和调试环境使用,切勿在生产环境中禁用哦~
绕过浏览器的同源策略
常用调试工具Chrome,支持配置添加--disabel-web-sercurity参数来禁用同源策略。
在Chrome路径后添加--disable-web-security --user-data-dir="自定义目录"(自定义目录,例:d:\ChromeData)
设置成功后,重新打开Chrome浏览器,都是以禁用浏览器同源策略的方式打开的,并且会带有相关的告警提示:
巧用浏览器CORS插件
在Chrome应用商店中搜索安装即可。
- CORS Unblock:解除跨域限制;
- Allow-Control-Allow-Origin:允许跨域资源共享(CORS);
- ModHeader:允许用户修改请求头,可以用于测试不同的 CORS 配置;
- Postman Interceptor:结合 Postman 工具使用,拦截请求和响应,方便测试和调试。
抓包工具代理请求
环境/代码配置解决跨域
1. JSONP
利用<script>标签不受同源策略限制的特点,通过动态插入<script>标签来请求跨域资源。
- 实现:
- 客户端,创建一个
<script>标签,将跨域请求的URL作为src属性。 - 服务器端:返回的数据需要以函数调用的形式包裹,客户端定义相应的回调函数来接收数据。
- 客户端,创建一个
- 缺点:只支持GET请求。
<button id="btn">获取数据</button>
<!-- <script src="http://localhost:3000?cb=callback"></script> -->
<script>
function jsonp(url, b) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = `${url}?cb=${cb}`
document.body.appendChild(script);
window[cb] = function(data) {
resolve(data)
}
})
}
let btn = document.getElementById('btn');
btn.addEventListener('click',()=>{
jsonp('http://localhost:3000','callback')
.then(res=>{
console.log('后端响应的数据:',res);
})
})
</script>
2. 跨域资源共享(CORS)
通过服务器端设置响应头信息来实现跨域请求。
- 服务器端
Access-Control-Allow-Origin:指定允许跨域请求的源,可以是具体的域名或通配符*;Access-Control-Allow-Methods:指定允许使用的请求方法,如GET、POST等;Access-Control-Allow-Headers:指定允许在请求中使用的头部字段;
- 客户端:浏览器会自动处理;
- 优点:支持所有类型的HTTP请求,是W3C推荐的标准跨域解决方案。
3. 代理(Proxy)
通过在服务器端设置一个代理服务器,前端与代理服务器通信,代理服务器与目标服务器通信,从而绕过浏览器的同源策略限制。
- 实现:使用NodeJS的中间件或者Nginx等服务器软件来设置代理
- 优点:灵活性强,可以配置复杂的路由规则;
例:前端页面部署在:http://10.168.17.122:9887,而后端服务部署在http://10.168.17.122:9888,由于端口不一致,前端请求会跨域,可通过nginx.conf配置,让两者处于同域名和同端口下,配置如下:
server {
listen 8080; # 端口
server_name localhost; # 域名
# 代理所有前端页面
location / {
proxy_pass http://10.168.17.122:9887;
}
# 代理后端接口
location /cors-api {
proxy_pass http://10.168.17.122:9888;
# 添加了部分自定义属性
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Headers *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, OPTIONS";
if ($request_method = 'OPTIONS') {
return 200;
}
}
}
4. PostMessage
使用window对象的postMessage方法在不同源的窗口之间发送和接收数据。
- 实现:
- 发送方:使用postMessage方法发送数据,并指定接收方窗口的引用。
- 接收方:监听message事件来接收数据。
- 场景:适用于两个页面之间的跨域通信,如iframe内的页面与父页面之间的通信
5. WebSocket
网络通信协议,可以在单个TCP连接上进行全双工通信。
- 跨域处理:WebSocket不受同源策略限制,可直接使用;
- 优点:支持实时通信,适合需要频繁传输数据的应用场景
6. 服务器端反向代理
服务器端设置。
优点:对前端透明,无需修改前端配置;
7. document.domain + iframe
通过设置document.domain属性使不同子域的页面具有相同的域,从而可以相互访问。
场景:适用于主域相同、子域不同的跨域应用场景
8. location.hash + iframe
- 原理:通过iframe和
location.hash来实现跨域通信。 - 实现步骤:
- 在一个页面中嵌入一个iframe,并设置其
src属性为另一个域的页面。 - 通过修改iframe的
location.hash值来传递数据,监听hashchange事件来接收数据。
- 在一个页面中嵌入一个iframe,并设置其