• JS中的跨域问题


    跨域访问出错信息:No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9100' is therefore not allowed access. The response had HTTP status code 400.

    1、跨域的概念

    跨域是指从一个域名的网页去请求另一个域名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。由于浏览器的同源策略跨域访问会受到限制。同源策略指的是域名、协议、端口号都相同,只要 协议,域名,端口有任何一个的不同,就被当作是跨域。

    URL由协议+主机名/域名+端口+路径+查询字符串+信息片段组成。

    http://mail.163.com:8000/index.html
    http://:是协议;mail:是服务器名;163.com:是域名;mail.163.com:这个是主机名(网站名),由服务器名+域名组成;8000:是端口号

    1.1、限制跨域访问的原因

    安全问题:如果一个网页可以随意地访问另外一个网站的资源,那么就有可能在客户完全不知情的情况下出现安全问题。比如

    比如一个黑客,他利用iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名和密码登录时,如果没有同源限制,他的页面就可以通过 JavaScript读取到你的表单中输入的内容,这样用户名和密码就轻松到手了.又比如你登录了OSC,同时浏览了恶意网站,如果没有同源限制,该恶意 网站就可以构造AJAX请求频繁在OSC发广告帖。

    但是有时跨域访问也是需要的,比如有时公司内部有多个不同的子域,比如一个是location.company.com ,而应用是放在app.company.com , 这时想从 app.company.com去访问 location.company.com 的资源就属于跨域。

    2、跨域的解决方法

    2.1、通过JSONP实现跨域

    JSONP 是 JSON with padding(填充式 JSON 或参数式 JSON)的简写,是应用 JSON 的一种新方法。JSONP 看起来与 JSON 差不多,只不过是被包含在函数调用中的 JSON, 比如:

    callback({ "name": "Nicholas" });   //callback:回调函数名  JSONP可以看做就是一段以json为参数的函数调用代码

    JSONP 由两部分组成:回调函数和数据。回调函数是当响应到来时应该在浏览器页面中调用的函数。

    JSONP 是通过<script>标签来使用的,使用时可以为src 属性指定一个跨域 URL。这里的<script>元素与<img>元素类似,都有能力不受限制地从其他域加载资源。因为 JSONP 是有效的 JavaScript 代码,所以在请求完成后,即在 JSONP 响应加载到页面中以后,就会立即执行。

    JSONP的原理:通过script标签引入一个 js 文件,这个 js 文件载入成功后会自动执行在 src 参数中指定的回调函数,并且后端会设计把需要的 json 数据作为参数传入。所以 jsonp 是需要服务器端进行配合设计的,即后端需获得前端传过来的回调函数名,并把需要的json数据作为参数,然后把一段回调函数执行的代码返回,当前端加载到后端页面时将收到后端返回的那段代码,然后自动执行回调函数。

    //前端代码
    <script type="text/javascript">
        function dosomething(jsondata){
            console.log('数据:', jsondata)
        }
    </script>
    <script src="http://example.com/data.php?callback=dosomething"></script>
    
    //后端代码
    <?php
    $callback = $_GET['callback'];//获取前端传来的回调函数名
    $data = array('a','b','c');//这是要返回的数据
    echo $callback.'('.json_encode($data).')';//输出 JSONP ,前端拿到这个输出将会执行这段代码
    ?>

    可以通过动态创建 script 标签来实现 JSONP,这样就不用在 html结构上添加额外的script标签了

    <input type="text" name="number" id="number" value="" />
    <p id="info"></p>
    <input type="button" name="" id="btn" value="查询" />
    <script type="text/javascript">
      var btn = document.getElementById("btn");
      var numbers = document.getElementById("number");
      var info = document.getElementById("info");
      btn.onclick = function () {
        var value = numbers.value;
        var script = document.createElement("script");
        script.src = "http://10.80.1.23/PHP/ajax/logistics/logistics.php?kuaidi_id=" + value + "&callback=show";
        document.body.appendChild(script);
      }
    
      function show(val) { // 插入数据
        info.innerText = "姓名:" + val.info + " 状态:" + val.status;
      }
    </script>

    JSONP的缺点:

    (1)它只支持GET请求而不支持POST等其它类型的HTTP请求
    (2)它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
    (3)jsonp在调用失败的时候不会返回各种HTTP状态码。
    (4)缺点是安全性。万一假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制的。那么结果是什么?所有调用这个 jsonp的网站都会存在漏洞。于是无法把危险控制在一个域名下…所以在使用jsonp的时候必须要保证使用的jsonp服务必须是安全可信的。

    2.2、CORS实现跨域

    CORS跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。

    对于前端开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。实现CORS通信的关键是服务器端,只要服务器实现了CORS接口,就可以跨源通信。如果服务器端实现了CORS,在进行AJAX请求时,浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求。

    CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。

    服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。只需要在后台中加上响应头来允许域请求!

    //指定允许其他域名访问
    'Access-Control-Allow-Origin:*'//或指定域
    //响应类型
    'Access-Control-Allow-Methods:GET,POST'
    //响应头设置
    'Access-Control-Allow-Headers:x-requested-with,content-type'
    //前端代码,跟一般ajax访问无区别
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4 && xhr.status == 200) {
        console.log(xhr.responseText)
      }
    }
    xhr.open('GET', 'http://192.168.2.186:8081/KuayuAjax/server.php', true);
    xhr.send(null);

    //后端代码
    <?php
    header("Content-Type:text/plain");
    header("Access-Control-Allow-Origin:http://localhost:8081");//设置头部,不设置的话请求会被拒绝
    echo '{"src":"http://www.pinkbluecp.cn/face_alignment/img/picture.jpg"}';
    ?>
  • 相关阅读:
    线程池的工作原理
    并发处理之master-worker 模式
    Parrot os引导修复
    使用datax mongodb导数据到postgresql数据库遇到访问权限问题
    10、Flink高可用HA
    9、Standalone集群测试运行
    8、Flink Standalone工作流程
    7、Flink Local模式安装部署
    java读取word文档的文字内容
    对文件内容就行修改-java代码
  • 原文地址:https://www.cnblogs.com/wenxuehai/p/10371692.html
Copyright © 2020-2023  润新知