likes
comments
collection

什么是“跨域”及解决跨域有(两种方案)

作者站长头像
站长
· 阅读数 18

1.跨域介绍

1.当你的浏览器出现跨域的时候,会有固定格式的报错

Access to XMLHttpRequest at 'http://127.0.0.1:3000/api/getbooks' from origin 'xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

2.跨域是什么?

 跨域 : "ajax请求地址""当前页面地址"  "不同源" , 称为跨域
    (1)ajax请求 : 跨域只会出现在ajax请求
        * ajax地址 : 服务器接口文档地址
    (2)当前页面地址 :  location.href
    (3)不同源 : 协议名、ip地址、端口号  只要有任意一个不相同,就是不同源

3.什么是同源

 同源 :  协议名、ip地址、端口号 三者一致就叫同源  
    当前页面地址 : http://127.0.0.1:3000/home/index.html
    ajax地址1 : https://127.0.0.1:3000/abc   (不同源,协议不同)
    ajax地址2 : http://127.0.0.1:3000/abc   (同源, 三码合一)
    ajax地址3 : http://192.168.48.81:3000/abc  (不同源, ip不同)
    ajax地址4 : http://127.0.0.1:4399/abc (不同源,端口号不同)

4.浏览器为什么要有这种跨域限制?

 *浏览器为了保护用户安全, 当用户ajax发送的地址 和 页面地址 
   不同源,浏览器会认为你向两个服务器发      送了请求,所以就会阻止这种行为。*
   

解决跨域有两种方案

   (1)CORS技术 :  现在主流解决方案, 不需要前端写任何代码
        方案:服务器只需要设置一个允许跨域响应头即可 
             res.setHeader('Access-Control-Allow-Origin', '*')
   (2)jsonp技术 : 以前的方案,现在很少使用。 原理和流程复杂,可以提现前端技术含量。
    
    
   (1)只有ajax请求才会出现跨域, 其他的请求不存在跨域 -->
         <a href="http://127.0.0.1:3000/abc">点我发请求</a>
   (2)点击按钮发送ajax请求
       <button>点我发送ajax请求</button>

   (3)jsonp技术解决跨域
    1.核心原理 : 利用script标签src属性来发送请求, 因为跨域只对ajax有限制
    2.了解script标签src属性做了什么事情 
        (1)给服务器发送请求
        (2)执行服务器响应返回的js代码
    3.jsonp完整流程
        (1)浏览器 : 声明一个函数,用于接收服务器响应数据
        (2)浏览器: 写一个script标签, 路径是jsonp请求地址,添加一个额外参数callback=函数名
        (3)服务器: 处理完请求之后, 返回一个函数调用的js代码,格式res.send( '函数名(响应数据)' )
            * 函数名需要从参数callback获取
    (4)浏览器就会执行script标签响应的js代码

CORS技术解决跨域


  const fn = res=>{
            console.log(res)
        }
    </script>

    <script src="http://127.0.0.1:3000/aaa?callback=fn"></script>

    <script>
        //cors按钮
        document.querySelector('button').addEventListener('click', function () {
            //(1).实例化ajax对象
            let xhr = new XMLHttpRequest()
            //(2).设置请求方法和地址
            //get请求的数据直接添加在url的后面 格式是 url?key=value
            xhr.open('get', 'http://127.0.0.1:3000/abc')
            //(3).发送请求
            xhr.send()
            //(4).注册回调函数
            xhr.onload = function () {
                console.log(xhr.responseText)
            }
        })
    </script>

jsonp技术解决跨域


<script>
        /* 
        1.jsonp整体工作流程(把jsonp封装到按钮点击事件里面)
            (1)浏览器: 声明函数接收服务器响应数据
            (2)浏览器: 点击按钮给页面添加script,添加额外参数callback=函数名
            (3)服务器 : 响应函数调用js代码   res.send('函数名(响应数据)')
            (4)浏览器: script标签会执行服务器响应的js
        
        */
       
        const getBook = res => {
            console.log(res)
            //一旦响应了jsonp数据之后,就移除script标签
            document.querySelector('#jsonp').remove()
        }

        document.querySelector('button').addEventListener('click', function () {
            //(1)声明函数接收服务器响应数据 (需要是全局函数)

            //(2)给页面动态添加script
            const script = document.createElement('script')
            script.src = 'http://127.0.0.1:3000/aaa?callback=getBook'
            script.id = 'jsonp'
            //一般动态jsonp会添加到head标签
            document.body.appendChild(script)
        })
    </script>

代码演示



            //1.导入模块
            const express = require('express')
            //2.创建服务器
            let app = express()


            //设置跨域中间件 : 类似于拦截器,会给每一个路由自动设置允许跨域响应头
            // //(1)导入模块
            // const cors = require('cors')
            // //(2)使用模块
            // app.use(cors())

            //1. cors技术解决跨域
            app.get('/abc',(req,res)=>{
                //允许跨域响应头
                res.setHeader('Access-Control-Allow-Origin', '*')
                //设置content-type响应头
                //响应数据
                res.send('<h1>我是html</h1>')
            })

            //2. jsonp技术解决跨域
            app.get('/aaa',(req,res)=>{
                console.log(req.url)
                console.log(req.query)
                //调用浏览器传递过来的那个函数名

                res.send(`${req.query.callback}(["西游记","水浒传"])`)
            })

            //3.开启服务器
            app.listen(3000, () => {
                console.log('success')
            })