前端开发中的跨域问题及解决方案

  • Post author:
  • Post category:其他




什么是跨域报错?

在这里插入图片描述



为什么会出现浏览器跨域报错?

简单来讲就是:不同源的ajax请求,具体来说满足以下三个条件就会出现跨域错误


1. 请求响应双方url不同源。


双方url:发出请求所在的页面 与 所请求的资源的url

​ 同源是指:

协议相同



域名相同



端口相同

都相同。


2. 请求类型是ajax请求



3. 浏览器觉得不安全


跨域问题出现的基本原因是浏览器的同源策略。

同源策略

是一个重要的安全策略,它限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。



解决思路

  1. 请求响应双方url不同源

    对策: 服务器代理
  2. 请求是ajax

    对策: 改发JSONP请求
  3. 浏览器觉得不安全

    对策1: 可以安装一个浏览器插件

    allow-control-allow-origin

    绕过同源策略。

    对策2: 用postman软件测试

    对策3: 使用cors



注意点

错误原因:

不同源



ajax请求

,后端还是能收到请求的,错误是发生在浏览器端

下面对于JSONP请求法和CORS方法展开讲述:



具体解决方案:



(一)JSONP请求法



实现原理

  1. script的src属性可以请求外部的js文件,这个请求不是ajax,它没有跨域问题.
  2. 借助

    script

    标签src请求服务端上的接口.
  3. 服务端的接口返回JavaScript 脚本,并附上要返回的数据.



实现方法1


1. 前端页面: 创建script标签并让src指向接口地址

<html>
    <script src="http://localhost:3000/get"></script>
</html>

注意点:

script标签中的src会指向一个后端接口的地址。由于script标签并不会导致跨域问题,所以这里的请求是可以正常发送和接收的。

与我们之前理解的src指向某个具体的.js文件不同,我们只需要确保src所指向的地址的返回内容是js代码就行了,而不必要src直接指向某个.js文件。

接口地址中返回的内容将会作为script标签的主体。


2. 后端:让接口返回函数调用表达式,并传入数据

const express = require('express');
const app = express();
app.get('/get', (req, res) => {
  const data =  JSON.stringify({a:1,b:2})
  const fnStr = `fn(${data})`
  res.end(fnStr); // 返回字符串,内容是:函数调用语句
})

app.listen(3000, () => {
  console.log('你可以通过http://localhost:3000来访问...');
});


3. 在前端页面补充fn函数

<script>
    function fn(rs) {
        console.log(rs);
    }
</script>
<html>
    <script src="http://localhost:3000/get"></script>
</html>



实现方法2 (简便操作)


1. 利用jQuery封装的jsonp方式,在前端页面给ajax请求添加一个dataType属性,其值为”jsonp”.

$.ajax({
   type: 'GET',
   url: 'http://localhost:4000/get', 
   success: function (result) {
      console.log(result);
   },
   dataType: 'jsonp' // 必须要指定dataType为jsonp
});


2. 在后端接口express框架提供了一个名为jsonp的方法来处理jsonp请求:

const express = require('express');
const app = express();
app.get('/get', (req, res) => {
  let data = {a:1,b:2}
  // res.json(data)
  res.jsonp(data)
})
app.listen(3000, () => {
  console.log('你可以通过http://localhost:3000来访问...');
});



特点


1. jsonp方法不是ajax请求



2. jsonp只能支持get方式



3. jsonp兼容性比较好



(二)cors方法



实现原理

CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest`请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10(ie8通过XDomainRequest能支持CORS)。



实现方法1 : 手写方法实现


通过在

被请求的路由中

设置header头,可以实现跨域。

app.get('/get', (req, res) => {
  // * 表示允许任何域名来访问
  res.setHeader('Access-Control-Allow-Origin', '*')
  // 允许指定源访问
  // res.setHeader('Access-Control-Allow-Origin', 'http://www.xxx.com')
  res.send(Date.now().toString())
})
  • 这种方案无需客户端作出任何变化(客户端不用改代码),就当跨域问题不存在一样。
  • 服务端响应的时候添加一个

    Access-Control-Allow-Origin

    的响应头



实现方法2: 使用cors包


下载nmp包 cors,当做express中的中间件使用,代码如下

const express = require('express')
const app = express()
app.use(express.static('public'))
app.use(express.json())
const cors = require('cors')
app.use(cors())
// get请求(解决跨域问题方案1)
app.get('/get',(req,res)=>{
    res.json({msg:'get请求,ok'})
})
// post请求
app.post('/postJSON',(req,res)=>{
    console.log('接收到的数据是', req.body)
    res.json({msg:'ok', data: req.body})
})

app.listen(3000, ()=>{
    console.log(3000);
})



特点


1.前端不需要做额外的修改,就当跨域问题不存在。



2.是ajax



3. 支持各种方式的请求(post,get…)



4. 浏览器的支持不好(标准浏览器都支持)



版权声明:本文为weixin_52119040原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。