bug-跨域访问问题

文章讲述了在大屏项目中遇到的跨域问题,通过分析发现自定义header是引发跨域的原因。给出了两种解决方案:前端移除自定义header,以及后端配置Access-Control-Allow-Headers。还介绍了JSONP、CORS、WebSocket等跨域解决方案和Nginx反向代理的原理。
摘要由CSDN通过智能技术生成

问题场景

  1. 自定义 header,导致跨域问题
    一个大屏项目,设置请求接口获取数据时,有的接口能够正常返回数据,有的接口提示跨域(接口域名不同),后端也进行支持跨域设置,结果还是提示跨域;
    通过测试发现,使用Axios直接请求,没有产生跨域,对比代码发现,请求拦截器添加了一个自定义header,去掉就正常了;
    问题原因是自定义header,后端配置应该也有问题导致的
    该问题是使用方式一处理的
  • 方式一:前端处理,去掉自定义 header;
  • 方式二:后端处理,Access—Control-Allow-Headers 配置中添加自定义 header,或改成*
  1. 使用chrome访问本地地址是提示跨域
    2.1 控制台报错: The request client is not a secure context and the resource is in more-private address space private
  • 方式一:使用火狐浏览器
  • 方式二:配置chrome
    在地址栏中输入chrome://flags/,
    找到 Block insecure private network requests.选项设置为Disabled,
    找到 Insecure origins treated as secure 选项设置为 Enabled,同时设置访问地址(如:http://192.169.16.200:8088)

2.2 控制台报错:Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
后端设置Access-Control-Allow-Origin

总结---------------------------------------------------------------------------------------------------------------

跨域是什么

是浏览器本身的安全策略产生的问题
当访问网页的域与页面内调用接口的域不一致(域不一致包含协议、域名、端口号不一致),就会产生跨域问题

跨域方案

  1. JSONP 方案

利用 <script> 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP 请求一定需要对方的服务器做支持才可以。

```
// 跨域加载资源标签
<img src=XXX>
<link href=XXX>
<script src=XXX>
```

```
<!-- 前端代码 -->
function jsonp(req) {
  let script = document.createElement("script"); // 创建一个script标签
  let url = req.url + "?callback=" + req.callback.name; // 拼接url
  script.src = url; // 设置script标签的src属性
  document.getElementsByTagName("head")[0].appendChild(script); // 将script标签添加到head标签中
}

function sayHello(res) {
  console.log("hello", res.data);
}
jsonp({
  url: "http://localhost:3000",
  callback: sayHello
})

```

```
<!-- 后端代码 -->
const http = require("http");
const urllib = require("url");

const port = 3000; // 定义端口

const server = http.createServer((req, res) => {
    let params = urllib.parse(req.url, true); // 解析url
    let callback = params.query.callback; // callback是函数名,解析出来
    if (callback) {
        let data = { data: "我就是你要的数据" }; // 定义要向前端返回的数据
        res.end(callback + "(" + JSON.stringify(data) + ")"); // 相应数据,callback(参数)的形式
    }
})

server.listen(port, function () {
    console.log("jsonp server is on");
});

```
  1. CORS
    CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。

  2. postMessage 与 message 事件
    window 与 iframe 之间通信

    <!-- 通过 postMessage 发送信息到指定位置数据 -->
    otherWindow.postMessage(message, targetOrigin, [transfer]);
    <!-- 通过 message 事件接收数据 -->
    window.addEventListener(“message”, dealMessage, false);
    
  3. websocket
    前后端使用 websocket 技术进行数据传递

  4. Node 中间件代理(二次跨域)
    实现原理:同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略。

  5. Nginx 反向代理
    类似 Node 中间件代理

当使用Vue下载文本文件时,可能会出现跨域问题。这是因为浏览器的安全策略要求在跨域请求时,服务器必须设置Access-Control-Allow-Origin响应头来允许客户端访问资源。 解决方法: 1. 在服务器端设置Access-Control-Allow-Origin响应头来允许跨域访问。 2. 在Vue中使用axios或fetch等工具发送请求时,需要设置withCredentials为true,以便发送跨域请求时能够携带cookies。 3. 将下载文件的请求改为后端处理,前端通过ajax请求后端,后端返回文件流数据,并设置Content-Disposition响应头来提示浏览器下载文件。 代码示例: 1.设置Access-Control-Allow-Origin响应头 ```js // Node.js Express框架示例 app.use(function(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With'); next(); }); ``` 2.使用axios下载文件 ```js axios.get('/download/file', { responseType: 'blob', withCredentials: true // 携带cookies }).then(res => { const url = window.URL.createObjectURL(new Blob([res.data])) // 创建下载链接 const link = document.createElement('a') link.href = url link.setAttribute('download', 'file.txt') document.body.appendChild(link) link.click() window.URL.revokeObjectURL(url) // 释放资源 }) ``` 3.使用ajax请求后端下载文件 ```js // 后端代码示例(Node.js) router.get('/download/file', function(req, res, next) { const filePath = path.join(__dirname, '../public/file.txt') const fileName = 'file.txt' res.setHeader('Content-Disposition', 'attachment; filename=' + fileName) res.setHeader('Content-Type', 'application/octet-stream') const readStream = fs.createReadStream(filePath) readStream.pipe(res) }) ``` ```js // 前端代码示例 axios({ url: '/download/file', method: 'get', responseType: 'blob', }).then((response) => { const url = window.URL.createObjectURL(new Blob([response.data])) const link = document.createElement('a') link.href = url link.setAttribute('download', 'file.txt') document.body.appendChild(link) link.click() window.URL.revokeObjectURL(url) }) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值