• 【无标题】


    本文节选自我的博客:解决跨域问题的 5 种办法

    • 💖 作者简介:大家好,我是MilesChen,偏前端的全栈开发者。
    • 📝 CSDN主页:爱吃糖的猫🔥
    • 📣 我的博客:爱吃糖的猫
    • 📚 Github主页: MilesChen
    • 🎉 支持我:点赞👍+收藏⭐️+留言📝
    • 💬介绍:The mixture of WEB+DeepLearning+Iot+anything🍁

    前言

    跨域问题一直是前后端交互过程中遇见频率最高的问题,本文带来五种解决跨域问题的办法,总有一种适合你。

    跨域

    什么是跨域?

    • 同源:两个资源的 协议、域名、端口都相同。否则就是跨域

    为什么要有跨域?

    • 浏览器的安全限制,为了防止读取非同源的DOM、Cookie、LocalStorage、IndexDB;

    跨域请求的过程?

    • 向非同源发起请求,请求资源跨域时,浏览器一般会先发起预检请求,检测资源是否支持跨域,再发起真实请求,请求类型为 preflight ,请求方法为OPTIONS 表示预检请求。

    解决跨域的五种方式

    1. 把协议、域名、端口改成相同的;
    2. 在响应头添加 Access-Control-Allow-Origin 相关字段来允许跨域,利用这种解决思路具体的实现的方式有 nginx配置、后端手动修改字段CORS、后端中间件请求拦截、谷歌插件等方式;
    3. JSONP,利用了script标签不受浏览器同源策略的影响;
    4. 反向代理,利用跨域只对浏览器有效,在node中开启跨域代理,负责请求转发。Vue和React都有代码配置,适用于开发环境;
    5. CSP(content-Security-policy)设置白名单。

    下面来展开聊其中的几个具体实现

    Nginx配置解决跨域问题

    在nginx服务器中配置,为响应头添加跨域字段

    location ^~ /api/ {
        add_header 'Access-Control-Allow-Origin' $http_origin; # 任何域名都支持跨域
        add_header 'Access-Control-Allow-Credentials' 'true';  # 允许前端带上cookie
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers '*';
        if ($request_method = 'OPTIONS') { # 如果是预检请求也要支持跨域
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Origin' $http_orig  in;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain; charset=utf-8';
            add_header 'Content-Length' 0;
            return 204;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    JSONP解决跨域问题

    JSONP利用了script标签不受浏览器同源策略的影响,可以通过src属性,请求非同源的js脚本。除了script标签,img、link标签也支持跨域。但是img只能跨域图片(其实也可以获取图片二进制再使用JS解析也能拿到数据,但没必要怎么做)、link只能跨域css。

    JSONP的4大缺陷:

    1. 只支持get请求
    2. 不安全
    3. 有缓存
    4. 传递信息有限制

    JSONP伪代码

    其实就是本地定义一个函数,用发起请求(发起的JS脚本请求)的方式调用自己
    前端HTML的代码

    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    同级目录JS文件夹下的getdata.js 文件

    abc({ name: 'ls', age: 30 })  //回调了HTML中的abc函数
    
    • 1

    实现JSONP

    前端部分

    
    
    
        
        
        Document
    
    
        
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Node后端部分

    const http = require('http')
    const url = require('url')
    const server = http.createServer()
    server.on('request',function(req,res){
        // 将api/test?callback=func 解析为 query和pathname urlobj是个对象还有一起其他内容
        let urlobj = url.parse(req.url,true)
        console.log(urlobj);
        if(urlobj.pathname === '/api/test'){
            // 返回了一个函数 func({name:'mileschen'})
            res.end(`${urlobj.query.callback}(${JSON.stringify({name:'mileschen'})})`)
        }else{
            res.end('404')
        }
    })
    server.listen(4433,function(){
        console.log('server start');
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    jQuery发起JSONP请求

    jQuery是通过动态创建和移除script标签的方式来发起JSONP请求。在发起SONP请求的时候,动态向

    中append一个