浅谈前端开发中的跨域问题

362 阅读3分钟

跨域

跨域是我们前端开发中经常会遇到的问题,那么跨域到底是什么,我们怎么去解决他们呢

问题演示

image.png
把前端代码单独运行就会报错了

image.png

跨域问题分析

原因:发起ajax请求的页面的地址和ajax接口地址不在同一个域中
跨域报错不同源ajax请求会导致报跨域的错误
同源:浏览器端和服务器端的协议域名端口号完全一样就是同源,只要有一个不一样就是跨域
跨域问题出现的根本原因:浏览器的同源策略,同源策略是一个重要的安全策略,它限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。
注意:错误是发送在浏览器端,请求是可以正常从浏览器端发送到服务器端,服务器也可以处理请求,只是返回到浏览器端的时候出错了

解决办法

  1. 让浏览器端和服务器端的三要素相同,处于同源
  2. 设置服务器代理
  3. 请求是ajax,改发JSONP
  4. CORS
  5. 通过在被请求的路由中设置header头,可以实现跨域 res.setHeader('Access-Control-Allow-Origin', '*')

手动实现解决跨域问题

通过在被请求的路由中设置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 的响应头

CORS解决跨域问题

  • CORS是一个W3C标准,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
  • CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10(ie8通过XDomainRequest能支持CORS)
  1. cors是一个npm包,需要单独下载使用
  2. 当做express中的中间件,注意代码应该放在顶部
const cors = require('cors')
app.use(cors())

这样做的好处是不用每个接口内部写res.setHeader

JSONP解决跨域问题

原理:

  1. script的src属性可以请求外部的js文件,这个请求不是ajax,它没有跨域问题
  2. 借助script的scr属性请求服务器上的接口
  3. 服务器的接口返回javascript脚本,并附上要返回的js数据代码,返回的数据必须加双引号(字符串类型)

JSONP的基本实现

在实际的开发中,前端使用jquery,后端使用nodejs+express
jquery中的ajax已经封装好了的jsonp方式,可以直接使用
改造一个接口,返回一个函数调用表达式
后端代码

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.send(fnStr); // 返回字符串,内容是:函数调用语句
})

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

前端代码

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

JSONP的实操

前端代码

    <!-- 引入jquery -->
    <script src="./js/jquery-1.12.2.js"></script>  
        <script>
        //调用jquery里面的方法
        $.ajax({
            type: 'GET',
            url: 'http://localhost:3000/getJSONP',
            success: function (result) {
                console.log(result);
            },
            dataType: 'jsonp' // 必须要指定dataType为jsonp
        });
    </script>

后端代码

// 静态资源托管,直接访问public.JSONP.html
//1. 导入包
const express = require('express')

//2. 调用
const app = express()

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

//4.jsonp
app.get('/getJSONP', (req, res) => {
    const data = { name: '薛之谦', music: ['怪咖', '笑场', '迟迟'] }
    res.jsonp(data)
})
//5.端口号监听,启动服务
app.listen(3000, () => {
    console.log('服务器已启动')
})

注意:原来是res.json,要改成res.jsonp

CORS和JSONP的区别

JSONP:

  • 不是ajax
  • 只能支持get方式
  • 兼容性比较好
    CORS:
  • 前端不需要做额任何的修改
  • 是ajax
  • 支持各种方式的请求
  • 浏览器的支持不太好