美文网首页H5前端技术分享程序员
跨域原理以及跨域解决方案

跨域原理以及跨域解决方案

作者: 胡哥有话说 | 来源:发表于2017-10-15 12:29 被阅读556次

    写在前面的话

    在火热的互联网IT时代,越来越多的前端开发工程师和H5开发工程师都会遭遇到人(猿)生中一个名词:跨域,尤其是新手第一次接触这个东西时,顿感手足无措。本篇文章将会对跨域从基本概念到详细应用进行一一解读,废话不多,直接走起....

    跨域到底是什么?

    先上张图,给各位压压惊...

    跨域错误提示信息

    是不是又看到了熟悉的 No 'Access-Control-Allow-Origin' (这是跨域的经典标志), 惊不惊喜,意不意外,是不是很熟悉!

    认识URL网址

    URL地址: http://www.justbecoder.com:80/article/index.html
        http                                  超文本传输协议
        www.justbecoder.com                   域名
        80                                    端口号
        article/index.html                    文件目录与文件名      
    

    同源策略

    概念

    同源策略是浏览器最核心也是最基本的的安全功能,是指我们在发送网络请求时请求必须要遵守同源策略,即域名、协议、端口号都要相同

    意义

    是为了保证用户信息的安全,防止恶意的网站窃取数据。

    触发跨域的场景以及原因

    当同源策略中的 域名、协议、端口号有一样不相同时,都会触发跨域

    假定当前在的网址是: http://www.justbecoder.com:80/,当我向以下网址发送请求时都会触发跨域
        url: https://www.justbecoder.com:80/   // 协议不同 --- 喂,老婆,我听不懂呀,你说话加密啦!
        url: http://www.baidu.com:80/          // 域名不同 --- 哎呀,菇凉认错认了,你不是我老婆
        url: http://www.justbecoder.com:8080/  // 端口不同 --- 是你老婆没错,但是你没有找对你老婆身上的门啊
    

    我们必须是用跨域吗?

    现在网站的功能越来越多,网站中的图片、视频、数据库有可能都不在同一台服务器上,不同协议、不同域名、不同端口号的服务器进行相互请求和响应是必然的,所以跨域一定是会使用到的!

    如何应用和解决跨域

    问题场景:

    // 客户端  跨域请求 --- 所在位置 http://localhost:80/index.js
    $.ajax({
        // 端口号不同,引发跨域
        url: 'http://localhost:3000/user/info',
        type: 'get',
        data: {
            id: 110
        },
        success: function(msg) {
            console.log(msg)
        },
        error: function(err) {
            console.log(err)
        }
    })  
    
    // 服务器端响应 --- 以Node.js为例,服务器位置http://localhost:3000
    var express = require('express');
    var router = express.Router();
    
    router.get('/user/info', function(req, res) {
        // 获取请求的参数
        // req.query.id // 当然这个参数目前是没有用滴...
        // ... 查询数据库中对应的用户info,假定当前获取的数据为
        var userInfo = {
            id: 110,
            username: '天王盖地虎',
            userimg: '/uploads/user/23456.jpg'
        };
        // 响应给客户端
        res.send(200, userInfo);
    })
    

    问题信息:

    当请求按照上面的代码进行发送和响应时,会触发跨域错误,因为二者的端口号是不一致的,没有遵循同源策略

    JSONP跨域请求解决方案:

    这里是重点,重点(敲黑板...),在使用script标签引入js文件时是不受同源策略影响的,so我们就可以拿这个做文章了

    // 当我们向某个位置发送请求时,请求和响应要做出如下改变
    客户端请求:
        <script src="http://localhost:3000/user/info?id=110" type="text/javascript"></script>
    服务器端响应:
        var userInfo = {
            id: 110,
            username: '天王盖地虎',
            userimg: '/uploads/user/23456.jpg'
        };
        
        // 序列化 -- 格式 {"id":110,"username":"天王盖地虎","userimg":"/uploads/user/23456.jpg"}
        var userInfoJsonStr = JSON. stringify(userInfo);
        
        // 格式 -- 'getInfo({"id":110,"username":"天王盖地虎","userimg":"/uploads/user/23456.jpg"})'
        res.send(200, 'getInfo('+userInfoJsonStr+')'); 
    
    客户端接收数据
        // 响应到的数据(浏览器 Network自行查看),该格式下的字符串,相当于在调用一个名字为 getInfo 的函数,传递的参数为 {"id":110,"username":"天王盖地虎","userimg":"/uploads/user/23456.jpg"}
        // getInfo({"id":110,"username":"天王盖地虎","userimg":"/uploads/user/23456.jpg"})
        
        在客户端的JS脚本中,定义对应的函数 getInfo()
        <script type="text/javascript">
            function getInfo(msg) {
                // 此处的msg就是获取响应的userInfo
                // 接下来你想干啥就干啥
            }
        </script>
    

    以上的这个过程,我们就解决了跨域的问题。

    JSONP跨域请求原理

    1. 创建script标签,将原有的url地址、参数数据设置为src的地址,并附加参数(包括约定的callback函数名)

       var script = document.createElement('script');
       script.src = 'http://localhost:3000/user/info?callback=getInfo&id=110';
       document.body.appendChild(script);
      
    2. 服务器端响应数据时,要将响应的数据设置为指定的格式 接收的函数名(JSON字符串格式数据)

       // 获取客户端约定的回调函数名
       var callback = req.query.callback;
       var userInfo = JSON.stringify({
           id: 110,
           username: '天王盖地虎',
           userimg: '/uploads/user/23456.jpg'
       });
       res.send(200, callback + '(' + userInfo + ')');
      
    3. 在客户端定义对应的函数名的函数,该函数的形参就是接收到的服务器端响应数据

       <script>
           function getInfo(msg) {
               // msg 服务器端的响应数据
               console.log(msg)
           }
       </script>
      

    jQuery封装的JSONP请求

    $.ajax({
        // 请求的url地址
        url: 'http://localhost:3000/user/info',
        // 发送数据方式
        type: 'get',
        // 参数
        data: {
            id: 110
        },
        // 请求成功时的callback
        success: function(msg) {
            // 你想干啥就干啥
        },
        // 预期服务器返回的数据类型
        dataType: 'jsonp',
        // 指定定义回调函数名的参数名,若不指定默认参数名为callback
        jsonp: 'callback',
        // 指定回调函数名,若不指定默认为系统自动生成
        // jsonpCallback: 'getInfo'
    })
    

    结语

    以上是我整理的关于跨域的原理以及相应的JSONP跨域解决方案,希望能够给各位小伙伴在工作和学习中提供一定的帮助。 欢迎小伙伴积极留言探讨,不要忘记收藏和点赞喜欢呦,还可以进行打赏,请哥喝杯咖啡呀。

    相关文章

      网友评论

      本文标题:跨域原理以及跨域解决方案

      本文链接:https://www.haomeiwen.com/subject/bjezyxtx.html