浏览器的跨域问题

什么导致的浏览器的跨域问题?

不同源的ajax请求会导致出现跨域的错误。--必须要是ajax请求,并且是不同源的才会出现跨域问题。跨域主要是出现在浏览器阻止了响应的接收(服务器有接收到请求也有发出响应),这里是浏览器存在同源策略

什么是同源?

同源是指请求和响应的地址中协议相同、域名相同、端口相同,只要一个不相同就是不同源。

制造一个跨域错误

文件目录结构

跨域
├── public
│   ├── js
│   │   └── axios.js
│   └── api.html 
└── app.js

前端代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <p>
        <button id="btn1_get">接口测试1:get请求带参数</button>
    </p>
    <p>
        <button id="btn2_post"> 接口测试2:post-传递普通键值对</button>
    </p>
    <p>
        <button id="btn3_postJSON">接口测试3:post-传递json</button>
    </p>
    <form id="myform">
        <input type="text" name="title">
        <input type="file" name="cover">
    </form>
    <button id="btn4_formdata">接口测试4:post-传递formdata</button>
    <hr />
    <script src="./js/axios.js"></script>
    <script>
        document.getElementById('btn1_get').addEventListener('click', () => {
            axios.get('http://localhost:3000/getapi', { params: { a: 1, b: 2 } })
        })
        var obj = {
            "name": "abc",
            "address": {
                "a": 1,
                "b": 2,
                "info": "c"
            }
        }
        document.getElementById('btn2_post').addEventListener('click', () => {
            const params = new URLSearchParams();
            params.append('param1', 'value1');
            params.append('param2', 'value2');
            axios.post('http://localhost:3000/post', params, {
                headers: { "content-type": "application/x-www-form-urlencoded" }
            })
        })

        document.getElementById('btn3_postJSON').addEventListener('click', () => {
            axios.post('http://localhost:3000/postJSON', obj)
        })

        document.getElementById('btn4_formdata').addEventListener('click', () => {
            var fd = new FormData(document.getElementById('myform'));
            axios.post('http://localhost:3000/publish',
                fd
            )
        })
    </script>
</body>
</html>

后端代码

// 静态资源托管,直接访问public/api.html
const express = require('express')
const app = express()

// 引包
const multer = require('multer')
// 配置,上传的文件都保存在uploads文件夹下面
const upload = multer({ dest: 'uploads/' })

// 托管静态资源
app.use(express.static('public'))

// 中间件--post请求普通键值对
app.use(express.urlencoded())

// 中间件--post请求参数json格式
app.use(express.json())

// 接口1--get
app.get('/getapi', (req, res) => {
  console.log('请求到的参数', req.query)
  res.send({ message: 'ok' })
})

// 接口2--post普通键值对
app.post('/post', (req, res) => {
  console.log('请求到的参数', req.body)
  res.send({ message: 'ok' })
})

// 接口3--post请求--json格式
app.post('/postJSON', (req, res) => {
  console.log('请求到的参数', req.body)
  res.send({ message: 'ok' })
})

// 接口4--文件的上传和下载
app.post('/publish', upload.single('cover'), (req, res) => {
  console.log('请求到的参数', req.body)
  console.log('请求到的文件参数', req.file)
  res.send({ message: 'ok' })
})

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

实现页面--通过localhost正确访问

跨域错误展示--这里是因为和请求的域名不同导致的跨域问题

这里的错误是指缺少了响应头,认为不安全就报错了

解决的方法

  1. 请求和响应双方不同源--借助服务器代理
  2. 不是ajax请求--jsonp
  3. 让浏览器绕过同源策略--cors

1、请求和响应双方不同源--借助服务器代理(还在了解当中,后续更新)

2、JSONP解决

jsonp是一种借助于script的src属性来实现跨域请求的,它的本质是,jsonp根本不是ajax请求来访问接口的,所以它并不存在跨域的问题。

jsonp的原理

jsonp是通过script标签中的src属性来请求服务器端的接口。

服务器端会返回一个携带数据的JavaScript脚本,到script标签的内部。

后端代码

//后端发送一个get请求
app.get('/getJSONP', (req, res) => {
  //后端传输的数据必须要是字符串类型
  const data = JSON.stringify({ arr: [1, 2, 3], name: '张三', age: 18 })
  const str = `fn(${data})`
  res.send(str)
})

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    function fn(obj) {
      console.log('接收到的数据', obj)
    }
  </script>
  //src中存放着接口地址
  <script src="http://localhost:3000/getJSONP">
  // 后端发送的数据会放在此处
  </script>
</head>
<body>
  <h1>JSONP</h1>
</body>
</html>

然后从页面就可以看到请求成功,并没有出现跨域的问题

3、让浏览器绕过同源策略--cors

这里需要去下载一个cors包,然后引入cors包,这样我们就可以解决跨域的问题了

// 引入包--cors
const cors = require('cors')
// 中间件
app.use(cors())

也可以在请求中加上这么一句来解决跨域

相当于服务端响应的时候添加一个 Access-Control-Allow-Origin 的响应头

// * 表示允许任何域名来访问
  res.setHeader('Access-Control-Allow-Origin', '*')

使用cors来解决跨域问题就相当于给返回的响应加了一个响应头

JSONP和cors两种方法的区别

jsonp:

        不是ajax;

        只能支持get请求;

        兼容性比较好。

cors:

        前端不用做修改,只需后端操作;

        是ajax;

        支持各种请求方式;

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值