同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。所谓的同源是指协议、域名和端口号都相同,如果有一个不同都不算是同源。
浏览器限制脚本内发起的跨源 HTTP 请求。 例如,XMLHttpRequest
和 Fetch API
遵循同源策略。这意味着使用这些 API 的 Web 应用程序只能从加载应用程序的同一个域请求 HTTP 资源,假如发送一个跨域请求,浏览器则会将响应结果丢弃,除非其符合CORS策略。
这是开发环境中最常用的一种跨域方法,在webpack或vite中进行相应的配置,然后由nodejs开发服务器代理请求转发给目标服务器,由于同源策略只在浏览器中起作用,从而绕开了同源策略的限制,开发服务器得到响应后再返回给浏览器。
// 以vite为例
export default defineConfig({
server: {
proxy: {
// 字符串简写写法
'/foo': '<http://localhost:4567>',
// 选项写法
'/api': {
target: '<http://jsonplaceholder.typicode.com>',
changeOrigin: true,
rewrite: (path) => path.replace(/^\\/api/, '')
},
// 正则表达式写法
'^/fallback/.*': {
target: '<http://jsonplaceholder.typicode.com>',
changeOrigin: true,
rewrite: (path) => path.replace(/^\\/fallback/, '')
},
// 使用 proxy 实例
'/api': {
target: '<http://jsonplaceholder.typicode.com>',
changeOrigin: true,
configure: (proxy, options) => {
// proxy 是 'http-proxy' 的实例
}
}
}
}
})
除了正向代理外,反向代理也可以解决跨域限制。反向代理解决跨域的思路是有两种
JSONP全称是json with Padding,这是一种比较老的解决方案。
jsonp的思路是
// 服务器 nodejs
const http = require("http");
const server = http
.createServer((req, res) => {
const data = 123 // 取数据
res.end(`cb(${data})`); // 数据作为参数
})
.listen("3333");
// 浏览器
<script>
// 定义好回调函数,后端数据会当做参数传入
function cb(data) {
console.log(`data是${data}`);
}
const scr = document.createElement("script");
scr.setAttribute("src", "<http://localhost:3333>");
document.documentElement.appendChild(scr);
</script>
jsonp解决跨域的本质是利用了script
等html标签所发送的http请求不受到同源策略的限制这一特性,script请求的内容会作为JavaScript代码直接执行,因此只需要和后端约定好回调函数名、要传回的数据等就可以使用jsonp完成跨域。
jsonp的优点是兼容性好,缺点也很明显:使用起来繁琐;只支持get方法;不安全,容易被跨站脚本攻击等。