跨域解决方案jsonp和cors

100 阅读2分钟

话不多说,直接前端代码如下:

jsonp

原理:利用的原理是script标签可以跨域请求资源,将回调函数作为参数拼接在url中。后端收到请求,调用该回调函数,并将数据作为参数返回去,注意设置响应头返回文档类型,应该设置成javascript。

html中首先声明回调处理函数,然后动态创建script标签发送请求信息

<body>
    <button id="btn">发送xml请求</button>
    <textarea name="" id="data" cols="30" rows="10"></textarea>
    <script>
        document.querySelector('#btn').addEventListener('click', () => {
            window.jsonpCallback = (res) => {
                document.querySelector('#data').innerHTML = JSON.stringify(res)
            }
            let script = document.createElement('script')
            script.type = 'text/javascript'
            script.src = 'http://localhost:8080/api/jsonp?id=1&cb=jsonpCallback'
            document.body.appendChild(script)
        })
        
    </script>
    <!-- <script src="http://localhost:8080/api/jsonp?id=1&cb=jsonpCallback" type="text/javascript"></script> -->
</body>

服务端需要安装koa或者express框架创建app,根据获得的回调格式使用相同的回调函数返回数据

const Koa = require('koa')
const app = new Koa()

const data = [
    {id: 1, title: '张三', age: 17},
    {id: 2, title: '李四', age: 18}
]

app.use(async (ctx, next) => {
    if(ctx.path === '/api/jsonp') {
        const { id, cb } = ctx.query
        const info = data.find(item => item.id == id)
        ctx.body = `${cb}(${JSON.stringify(info)})`
        return
    }
})

app.listen(8080, () => console.log('listen 8080 ...'))

cors

原理:目前最常用的一种解决办法,通过设置后端允许跨域实现。

使用XMLHttpRequest创建ajax请求,这里使用axios或者其他的ajax封装库都一样

<body>
    <button id="btn">发送xml请求</button>
    <textarea name="" id="data" cols="30" rows="10"></textarea>
    <script>
        document.querySelector('#btn').addEventListener('click', () => {
            const XML = new XMLHttpRequest()
            XML.open('get', 'http://localhost:8080/api/xml')
            XML.send()
            XML.onreadystatechange = () => {
                if(XML.readyState === 4 && XML.status === 200) {
                    document.querySelector('#data').innerHTML = XML.response
                }
            }
            XML.onerror = (e) => {
                console.error('err:' + e);
            }
        }) 
        
    </script>
</body>

设置响应体的头部的两个属性如下即可:'Access-Control-Allow-Origin', '*''Access-Control-Allow-Methods', 'OPTIONS, GET, PUT, POST, DELETE'。(也可使用cors封装库,此处省略)

const Koa = require('koa')
const app = new Koa()

const data = [
    {id: 1, title: '张三', age: 17},
    {id: 2, title: '李四', age: 18}
]

app.use(async (ctx, next) => {
    ctx.set('Access-Control-Allow-Origin', '*');
    ctx.set('Access-Control-Allow-Methods', 'OPTIONS, GET, PUT, POST, DELETE');
    if(ctx.path === '/api/xml') {
        ctx.body = `${JSON.stringify(data)}`
        return
    }
})

app.listen(8080, () => console.log('listen 8080 ...'))

其他方案

其他方案本人用的比较少,此处不详细代码阐释。

  • node中间件、nginx反向代理

    跨域限制的时候浏览器不能跨域访问服务器,node中间件和nginx反向代理,都是让请求发给代理服务器,静态页面面和代理服务器是同源的,然后代理服务器再向后端服务器发请求,服务器和服务器之间不存在同源限制

  • postmessage

    H5新增API,通过发送和接收API实现跨域通信。

    <body>
        <script>
            //这个只是给自己本地发送信息
            const msg = { name: '昂三' }
            window.postMessage(msg, 'http://127.0.0.1:5500')
            window.addEventListener('message', (e) => {
                console.log(e.data);
                console.log(e.origin);
                console.log(e.source);
            })
        </script>
    </body>
    

最后

有疏漏之处,请斧正。。。