前后端跨域问题

123 阅读2分钟

跨域

跨域是指发送请求的客户端和服务器之间,它们的 协议、域名/IP地址、端口号 三者中任意一个不相同 (由于浏览器的同源策略,禁止js从一个域名向另一个域名请求数据)

解决方式

配置CORS跨域资源共享(xhr2)

CORS允许浏览器向跨域服务器发送ajax请求

服务端

    //创建模块
    cost express = require('express')
    const cors = require('cors') 
    //创建服务
    let app = express()
    app.use(cors())

cors中间件其实做了下列事情:

 app.all("*",function(req,res,next){
     //设置允许跨域的域名,*代表允许任意域名访问
     res.header("Access-Control-Allow-Origin","*")
     //允许的header类型
     res.header("Access-Control-Allow-Headers","Content-Type")
     //允许的跨域请求方式 
     res.header("Access-Control-Allow-Methods","POST,GET")
     next()
 })

服务端代理转发(nodejs nginx webpack ...)

服务端没有跨域限制: 前端发送请求 <-> 自己的服务器 <-> 请求别人的服务器

  • node js

    客户端 :传入地址

        let target = 'https://m.you.163.com/xhr/index.json'; //跨域地址
        ajax({
            url: 'http://localhost:9999/user/proxy',// 访问同源地址
            data: {url:target}//传入地址
        })
    

    服务端:设置代理接口

        const http = require('http')
        app.get('/proxy',(req,res)=>{
            let {url} = req.query
            let data = ''
            http.get(url,(response)=>{
                //收到一个数据片段时,触发data事件
                response.on('data',(chunk)=>{
                    console.log('------------------')//分割流
                    data += chunk
                })
                //数据片段传输完成后,触发end事件
                response.on('end',()=>{
                    res.send(data)
                })
            })
        })
    
  • nginx:设置接口 (客户端:访问同源地址)

    服务端

        location = /proxy {
            proxy_pass 'https://m.you.163.com/xhr/index.json' //跨域地址
        }
    

使用jsonp跨域:只能适用get请求

jsonp是指跨域获取json数据

  • 由于浏览器的同源策略,禁止js跨域请求数据
  • 但是,浏览器不限制link img script等标签的跨域获取资源的能力
  • script标签,浏览器自动解析js

jsonp的实现:

  • 1.动态创建script标签
  • 2.将接口地址赋值给src属性,并在地址后面拼接参数
  • 3.将script标签添加到页面中
    • 客户端创建全局函数
    • 服务端调用函数,返回数据
  • 4.数据加载完成后,删除script标签

客户端:创建全局函数并添加script标签

    // 1.动态创建script标签
    let myScript = document.createElement('script');
    // 2.将接口地址赋值给src属性,并在地址后面拼接参数
    myScript.src = 'http://localhost:2000/user/jsonp?callback=test';
    // 3.将script标签添加到页面中
    document.body.appendChild(myScript);
    // 4.数据加载完成后,删除script标签
    myScript.onload = function (){
        this.remove();
    }
    //创建全局函数
    function test(json){
        console.log( '成功',json );//返回json对象 -> 浏览器自动解析js 
    }

服务端:接收回调函数

    app.get('/jsonp',(req,res)=>{
        //接收全局函数
        let {callback} = req.query
        let data = {
            username:'哈哈',
            age:20
        }
        res.send(`${callback}(${JSON.stringify(data)})`)//data为json字符串
        //res.send(test(data))
    })