一、什么是跨域请求
跨域请求是指在一个域名下的文档或程序试图去请求另一个域名下的资源,这种行为是被同源策略所禁止的。Same-origin policy是一种安全机制,它限制了从同一个源加载文档或脚本的非同源的请求。但是在实际开发中,我们经常需要跨域进行数据的交互,如何实现跨域请求就成为一个十分重要的问题。
二、XMLHttpRequest的基本使用
XMLHttpRequest对象是实现AJAX的基础。它可以在无需重新加载整个页面的情况下,向服务器发出请求和接收响应。下面是一个基本的XMLHttpRequest使用方法:
var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://www.example.com', true); xhr.onreadystatechange = function () { if(xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responseText); } }; xhr.send();
首先需要创建一个XMLHttpRequest对象,并使用open()方法指定HTTP方法(GET或POST)、请求的URL和是否异步处理。接着定义onreadystatechange事件,该事件在请求状态发生变化时触发,我们在其中对请求的状态做出处理。最后,我们使用send()方法来发送请求,如果发送的是POST请求,则需要传递参数。
三、常见的跨域请求方式
1. JSONP(JSON with Padding)
JSONP是一种跨域请求方式,它实现起来非常简单,只需要定义一个回调函数就可以了。在HTML页面中,定义一个script标签,并指定请求的URL和回调函数名称:
<script type="text/javascript"> function handleResponse(data) { console.log(data); } var script = document.createElement('script'); script.src = 'http://www.example.com/data?callback=handleResponse'; document.head.appendChild(script); </script>
服务器需要将数据封装在回调函数中返回,如:
handleResponse({"name": "John", "age": 30, "city": "New York"});
相对于XMLHttpRequest,JSONP有一个很大的优点,就是可以跨域调用服务器端的函数。但是JSONP也有它的不足之处,它只能支持GET请求,不能处理POST请求等复杂请求。
2. CORS(Cross-Origin Resource Sharing)
CORS是一种标准的跨域请求方式,它通过在服务端设置特殊的HTTP头信息来实现跨域。在前端代码中,我们只需要像普通的XMLHttpRequest一样发送请求即可,如下:
var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://www.example.com', true); xhr.withCredentials = true; // 设置跨域允许发送Cookie xhr.onreadystatechange = function () { if(xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responseText); } }; xhr.send();
服务器端需要设置Access-Control-Allow-Origin头信息,允许指定的域名进行跨域请求:
Access-Control-Allow-Origin: http://www.example.com Access-Control-Allow-Credentials: true // 允许跨域发送Cookie
CORS可以支持复杂请求,如POST、PUT和DELETE等,相比JSONP更为灵活。但是CORS要求服务器端必须设置相应的头信息,如果服务器没有正确设置,那么请求会被浏览器拦截。
3. 代理请求
代理请求是一种将跨域请求转化为同域请求的方法。我们可以在自己的服务器端定义一个代理接口,在这个接口中发出跨域请求,并将请求结果返回给前端页面。前端页面通过调用同域的代理接口实现跨域请求,下面是一个代理请求的实现示例:
代理接口代码:
app.get('/proxy', function (req, res) { var targetUrl = req.query.url; request(targetUrl, function (error, response, body) { if (!error && response.statusCode == 200) { res.send(body); } }); });
前端请求代码:
var xhr = new XMLHttpRequest(); xhr.open('GET', '/proxy?url=' + encodeURIComponent('http://www.example.com'), true); xhr.onreadystatechange = function () { if(xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responseText); } }; xhr.send();
代理请求可以实现跨域请求,但是要求在服务器端进行额外的编码和处理,增加了服务器端的负担。
四、总结
以上就是几种常见的跨域请求方式,每种方式都有自己的优缺点。在实际开发中,我们需要根据具体的情况选择合适的跨域请求方式。最后要注意,在跨域请求时,我们需要保证数据的安全性。避免在跨域过程中数据被篡改或窃取。