JS 跨域资源:原理、方法与实践

01-04 6216阅读

一、引言

在现代 Web 开发中,JavaScript 跨域资源访问是一个常见但又颇具挑战性的问题。当浏览器执行 JavaScript 代码时,出于安全考虑,会遵循同源策略(Same-Origin Policy),限制网页从不同源(协议、域名、端口任意一个不同)加载资源。然而,在实际项目中,跨域请求又是不可避免的,比如调用第三方 API 等。本文将深入探讨 JS 跨域资源的相关知识,包括原理、解决方法以及实践案例。

二、同源策略与跨域问题

(一)同源策略

同源策略是浏览器的一种安全机制,它规定只有当两个页面的协议(protocol)、域名(domain)和端口(port)都相同时,才允许它们之间进行相互访问。例如,http://www.example.com:8080http://www.example.com:8081 因为端口不同,就属于不同源。

(二)跨域问题的表现

当尝试进行跨域请求时,浏览器会在控制台抛出类似 Access to XMLHttpRequest at 'http://other-domain.com/api' from origin 'http://current-domain.com' has been blocked by CORS policy 的错误信息,阻止请求的正常进行。

三、解决跨域资源问题的方法

(一)CORS(跨域资源共享)

CORS 是一种 W3C 标准,它允许服务器声明哪些源站通过浏览器有权限访问哪些资源。

  1. 服务器端配置在服务器响应头中添加相关字段,例如在 Node.js(Express 框架)中:

    const express = require('express');
    const app = express();

// 允许所有源访问(实际项目中应按需配置) app.use((req, res, next) => { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); next(); });

// 示例路由 app.get('/api/data', (req, res) => { res.json({ message: '跨域请求成功' }); });

const port = 3000; app.listen(port, () => { console.log(服务器运行在 http://localhost:${port}); });

上述代码中,`Access-Control-Allow-Origin` 设置允许访问的源(`*` 表示所有源),`Access-Control-Allow-Methods` 声明允许的请求方法,`Access-Control-Allow-Headers` 规定允许的请求头。

2. **浏览器端请求**
在浏览器端使用 `fetch` 或 `XMLHttpRequest` 进行请求,与同源请求写法基本一致:
```javascript
fetch('http://other-domain.com/api/data')
   .then(response => response.json())
   .then(data => console.log(data))
   .catch(error => console.error('请求错误:', error));

(二)JSONP(JSON with Padding)

JSONP 利用 <script> 标签没有跨域限制的特性来实现跨域请求。

  1. 服务器端准备

    const express = require('express');
    const app = express();

app.get('/api/jsonp', (req, res) => { const callback = req.query.callback; const data = { message: 'JSONP 跨域数据' }; res.send(${callback}(${JSON.stringify(data)})); });

const port = 3001; app.listen(port, () => { console.log(JSONP 服务器运行在 http://localhost:${port}); });

服务器接收 `callback` 参数(前端传递的函数名),将数据包裹在该函数调用中返回。

2. **浏览器端实现**
```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>JSONP 示例</title>
</head>

<body>
    <script>
        function handleData(data) {
            console.log('接收到的数据:', data);
        }
    </script>
    <script src="http://localhost:3001/api/jsonp?callback=handleData"></script>
</body>

</html>

通过动态插入 <script> 标签,指定 src 为跨域接口并带上 callback 参数,实现跨域数据获取。但 JSONP 只支持 GET 请求,有一定局限性。

(三)代理服务器

可以在本地启动一个代理服务器,将跨域请求转发到目标服务器。例如在 Vue.js 项目中(基于 vue-cli),在 vue.config.js 中配置:

module.exports = {
    devServer: {
        proxy: {
            '/api': {
                target: 'http://other-domain.com', // 目标跨域域名
                changeOrigin: true,
                pathRewrite: {
                    '^/api': '' // 路径重写,去掉请求路径中的 /api
                }
            }
        }
    }
};

这样在前端代码中请求 /api/data 时,实际上会被代理到 http://other-domain.com/data,绕过浏览器的跨域限制。

四、实践案例

假设我们有一个前端项目需要获取天气数据(接口在另一个域名下),采用 CORS 方法:

  1. 天气接口服务器(Node.js + Express)

    const express = require('express');
    const app = express();
    const weatherData = { temperature: 25, condition: '晴天' };

app.use((req, res, next) => { res.setHeader('Access-Control-Allow-Origin', 'http://frontend-domain.com'); // 允许前端域名访问 next(); });

app.get('/weather', (req, res) => { res.json(weatherData); });

const port = 4000; app.listen(port, () => { console.log(天气接口服务器运行在 http://localhost:${port}); });

2. **前端项目(HTML + JavaScript)**
```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>天气数据获取</title>
</head>

<body>
    <script>
        fetch('http://localhost:4000/weather')
           .then(response => response.json())
           .then(data => {
                console.log('当前天气:', data);
                // 可以进一步在页面展示数据等操作
            })
           .catch(error => console.error('获取天气数据错误:', error));
    </script>
</body>

</html>

通过合理配置服务器端的 CORS 响应头,前端顺利获取到跨域的天气数据。

五、总结

JS 跨域资源问题在 Web 开发中广泛存在,CORS、JSONP 和代理服务器等方法为我们提供了有效的解决方案。在实际项目中,应根据具体需求(如请求方法、安全性要求等)选择合适的跨域方案。随着技术的发展,CORS 因其更符合现代 Web 标准、安全性更高且支持多种请求方法等优势,正成为解决跨域问题的主流选择。开发者需要不断学习和实践,确保跨域资源访问既满足功能需求,又保障系统安全。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

目录[+]