解决跨域的三种方法

解决同源政策问题的几种方法

01-jsonp方法

  • 在html文件里面写
<body>
    <button>提交1</button>
    <button>提交2</button>
    <script>
        // 要将全局作用的function也弄到其中
        var btn = document.querySelector('button:first-child')
        var btn1 = document.querySelector('button:nth-child(2)')
        btn.onclick = function() {
            jsonp({
                url: 'http://localhost:3001/sever',
                data: {
                    name: 'jinkai',
                    age: 20
                },
                success: function(data) {
                    console.log('btn1点击的')
                    console.log(data)
                }
            })
        }

        btn1.onclick = function() {
            jsonp({
                url: 'http://localhost:3001/sever',
                data: {

                },
                success: function(data) {
                    console.log('btn2点击的')
                    console.log(data)
                }
            })
        }


        function jsonp(options) {
            // 为了接收更多参数使用jsonp里面要加上data
            var script = document.createElement('script')
            var parms = ''
            for (var atter in options.data) {
                parms += '&' + atter + '=' + options.data[atter]
            }
            var fn = 'json' + Math.random().toString().replace('.', '')
            script.src = options.url + '?callback=' + fn + parms
            document.body.appendChild(script)
            window[fn] = options.success
            script.onload = function() {
                document.body.removeChild(script)
            }
        }
    </script>
</body>

</html>
  • 在服务器s2里面填写
var express = require('express')
var path = require('path')
var app = express()
app.use(express.static(path.join(__dirname, 'public')))

app.get('/sever', function(req, res) {
    // 将名字动态弄到了服务端
    // const fname = req.query.callback
    // const data = fname + '({name: "张三", age: "20"})'
    // res.send(data)

    //+服务器代码优化
    // const fname = req.query.callback
    //     // 将json格式代码转化data
    // const data = JSON.stringify({ name: "张三", age: "20" })
    // const result = fname + '(' + data + ')'
    // res.send(result)

    // 看似上面代码很优秀,其实还有语法糖
    // res提供了jsonp方法,其实原理就是上面代码(换汤不换药)
    res.jsonp({ name: "张三", age: "20" })
})
  • 总结:
    • 1.jsonp封装函数就是新建script标签里面填写不同的src地址,然后被服务端接收,服务端发送函数调用。
    • 2.了解了基本概念之后封装函数就会非常快!
    • 3.Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

02-CORS跨域方法

  • 实现cors跨域很简单,ajax方法照常使用,但是要在不同域的服务端写下如下代码。
//注意:如果跨域请求中涉及到cookie信息传递,值不可以为*号 比如是具体的域名信息
 res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
    //     // 2.允许客户端使用哪些请求方法访问我
res.header('Access-Control-Allow-Methods', 'get,post')
  • 假设有很多请求,都一一写哪两个设置的话重复代码太多了可以这样写
app.use((req, res, next) => {
    // 1.允许哪些客户端访问我
    // * 代表允许所有的客户端访问我
    // 注意:如果跨域请求中涉及到cookie信息传递,值不可以为*号 比如是具体的域名信息
    res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
        // 2.允许客户端使用哪些请求方法访问我
    res.header('Access-Control-Allow-Methods', 'get,post')
        // 允许客户端发送跨域请求时携带cookie信息
    res.header('Access-Control-Allow-Credentials', true);
    next();
})
  • 总结:
    • 1.打开设置的请求就可以跨域
    • 2.记住每次打开的时候要重启服务器。

发现了一个奇怪的问题,就是每次写完CORS跨域再重新打开服务器,虽然能访问了。但是我如果删掉设置代码,还是能够跨域,浏览器的network里面还是可以看到

03-访问非同源数据的服务器端解决

  • 这是间接的访问

例:(两个服务器s1,s2)在s1的app.js里面开启服务,s1里面的html文件访问本地的http://localhost:3000/s1 地址.但是本地s1里面有request第三方请求包。再通过服务器访问其他服务器就可以达到跨域效果。
要先安装request第三方包再s1里面(npm install request)

  • s1服务器html文件
<button id="button">点击按钮</button>
<script src="/js/ajax.js"></script>
<script>
    var btn = document.getElementById('button')
        /// url地址写的是s1服务器,然后通过服务器来跨域
    btn.onclick = function() {
        ajax({
            type: 'get',
            url: 'http://localhost:3000/jianjie',
            success: function(data) {
                console.log(data)
            }
        })
    }
</script>
  • s1服务器
app.get('/jianjie', function(req, res) {
    request('http://localhost:3001/cross', function(err, response, body) {
        res.send(body)
    })
// request里面的回调函数参数讲解:err 是错误信息
// response是一些请求的相关信息
// body是s2服务器发送的数据
})
  • s2服务器
app.get('/cross', function(req, res) {
    res.send('我是cross')
})
  • 简单介绍一下流程
    1. s1服务器想要接收s2服务器里面的响应
    2. 所以s1服务器html文件通过ajax请求来访问s1服务器端
    3. s1服务器端再通过request来间接的响应s2服务器

简单的比较一下,总结一下

  • CORS和JSONP比较(来源于:[阮一峰博客]http://www.ruanyifeng.com/blog/2016/04/cors.html)
    CORS与JSONP的使用目的相同,但是比JSONP更强大。
    JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
  • 访问非同源数据的服务器端解决方案
    记住这个是间接的访问!
posted @ 2020-11-17 15:31  咬紧牙关  阅读(345)  评论(0)    收藏  举报