随着单页面应用 (SPA) 的流行,前端开发中的跨域问题也随之而来。当前端应用通过 AJAX 发起跨域请求时,由于浏览器的安全限制,服务器会拒绝该请求并返回一个错误。本文将探讨在 SPA 应用中如何解决跨域问题。
什么是跨域
在同源策略 (Same-Origin Policy) 的限制下,浏览器允许同一个域名下的网页发送 AJAX 请求,而拒绝不同域名的网页发送请求。不同域名之间包括协议、主机名和端口号的任何不同。
例如,当你的前端应用运行在 https://www.example.com
上,但是要从 https://api.example.net
发送 AJAX 请求时就会触发跨域问题。浏览器默认是不允许这种跨域请求的。
解决跨域问题的方法
CORS (Cross-Origin Resource Sharing)
CORS 是 W3C 标准,全称为跨域资源共享。浏览器允许跨域请求时,会在请求头中增加 Origin
字段,表示当前请求的来源。服务器可以在响应头中增加 Access-Control-Allow-Origin
字段,指定允许来源的域名。
实际上,CORS 的实现并不需要手动设置响应头。如果服务器返回的响应中不包含 Access-Control-Allow-Origin
字段,浏览器会拒绝该请求。只有在响应头中包含这个字段时,浏览器才会接受跨域请求。
在服务器端设置响应头
在服务器端设置响应头的方法因语言不同而不同。下面以 Node.js 为例,演示如何在服务器端设置跨域响应头。
const express = require('express') const app = express() // 允许所有来源的跨域请求 app.use(function(req, res, next) { res.header('Access-Control-Allow-Origin', '*') next() })
上面的代码中,Access-Control-Allow-Origin
字段设置为 *
表示允许所有来源的跨域请求。如果你想限制来源,可以把 *
替换成允许的域名,例如:
res.header('Access-Control-Allow-Origin', 'https://www.example.com')
在客户端发送 AJAX 请求
在客户端发送 AJAX 请求时,只需要加上 withCredentials: true
字段就能启用跨域携带认证信息。例如:
fetch('https://api.example.net', { credentials: 'include', })
JSONP (JSON with Padding)
JSONP 是一种利用 <script>
标签实现跨域请求的方法。当客户端请求第三方 API 时,可以将请求转换成一个回调函数,然后通过 <script>
标签发送到第三方网站。当接收到响应后,第三方网站会把数据包裹在函数调用中返回给客户端。
JSONP 的实现方法如下:
在客户端定义回调函数
function handleResponse(data) { console.log(data) }
通过 script 标签发送请求
<script src="https://api.example.net?callback=handleResponse"></script>
其中,callback=handleResponse
表示请求回调函数为 handleResponse
。
在第三方网站返回数据时调用回调函数
handleResponse({"name": "John", "age": 30})
返回的数据会自动被包裹在回调函数中,客户端就能获取到响应数据了。
反向代理
反向代理是将客户端请求转发到后台服务的一种技术。通过反向代理,前端应用可以直接访问后台服务的接口,避免了跨域问题。
反向代理的实现方法如下:
在服务器端设置路由
// 将 /api 路径下的请求转发到 http://localhost:3000/api app.use('/api', createProxyMiddleware({ target: 'http://localhost:3000', changeOrigin: true, }))
上面的代码中,使用 createProxyMiddleware
函数创建一个代理中间件,并将 /api
路径下的所有请求转发到 http://localhost:3000/api
。
在客户端发送请求
fetch('/api/users')
上面的代码中,客户端只需要通过 /api
路径访问后台服务,反向代理会自动帮你转发请求到 http://localhost:3000/api
。
总结
跨域问题是前端开发中常见的问题,其本质是浏览器对同源策略的限制。本文介绍了三种解决跨域问题的方案:CORS、JSONP 和反向代理。当前端应用需要访问外部服务接口时,可以根据需求选择合适的解决方案。
参考资料
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/644fc9a8980a9b385b915ec0