网站开发跨域问题解决方案
什么是跨域问题?
跨域问题,即浏览器报 Error: Access to XMLHttpRequest at ‘http://example1.com’ from origin ‘http://example2.com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. 这个错误。
这是因为:
处于安全原因,浏览器会限制由脚本发起的 HTTP 请求,例如,XMLHttpRequest 和 Fetch API 都应遵循同源策略。这意味着一个 web app 只能请求与它本身同源的资源 API,除非一个不同源的 API 配置了正确的 CORS 头。
For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy. This means that a web application using those APIs can only request resources from the same origin the application was loaded from unless the response from other origins includes the right CORS headers. (Cross-Origin Resource Sharing (CORS) - MDN)
*同源:如果两个 URL 的 protocol、port 和 host 都相同的话,则称这两个 URL 是同源。
解决方案
- (仅开发环境下)修改浏览器安全策略
跨域拦截是客户端浏览器的行为,为了开发的方便,开发者可以暂时屏蔽掉这一项安全策略。
例如,<新版chrome浏览器设置允许跨域> --haorooms 中介绍了 手动重设 chrome 浏览器该配置的方法。
此外,Moesif CORS 等浏览器插件也可实现同样的功能。
当然,这样的方法只适用于开发环境,因为你作为开发者不应该干涉用户的安全配置。
- (仅开发环境下)webpack-dev-server 代理
在使用 webpack-dev-server 的时候,可以通过在 webpack.config.js 中配置 proxy 实现跨域。即请求会指向 dev-server,由 dev-server 再向 target 做请求。这样对浏览器来说,前后端总是同源的,因为他们都在 dev-server 上。
例如如下的配置:
(可参考 devserver-proxy --webpack文档)
- 服务端反向代理(网关)
服务端反向代理是解决跨域问题的最常见办法!大多数服务端框架都支持此功能,常见如 nginx(nginx HttpProxy模块)、Apache(Apache 反向代理指南)、Express(http-proxy-middleware)等。
通过在服务端配置反向代理,对浏览器(客户端来说)页面和各种资源、API都是同源的。
- JSONP
jsonp 是一种传统的处理跨域问题的方案,其原理是使用
它的缺点在于,一是只能获取数据,而不能向后端回传数据,二是请求得到的结果会被直接执行,可能会有安全风险。
- CORS
CORS(Cross-Origin Resource Sharing)是对跨域问题的终极解决办法。它由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应。
针对简单请求,浏览器会直接发出 CORS 请求,其头部会包含一个 Origin 字段。如果请求的源符合后端要求,那么返回的头中会包含 Access-Control-Allow-Origin, Access-Control-Allow-Credentials 等字段,可以被浏览器正常解析。
针对非简单请求,浏览器会先做一次 OPTIONS (预检)请求,在确认后端支持该 CORS 请求时再发出正式请求,否则正式请求不会被发出。
参考 阮一峰的网络日志:跨域资源共享 CORS 详解
-
iframe
可以在页面中以 iframe 的方式加载目标域下的页面,通过 postMessage 的方法请求该域下的数据,以此避免跨域问题。 -
webSocket
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。基于 WebSocket 的通信不存在跨域问题。