• 跨域问题


    1.为什么会出现跨域问题?

      浏览器的同源策略限制,浏览器会拒绝跨域(拒绝读操作)请求。【服务器与服务器之间的数据请求不会存在跨域】

    2.什么叫同源?

      如果两个页面拥有相同的协议(protocol),端口(port)和主机(host),那么这两个页面就属于同一个源(origin)。【二级域名不同也属于不同主机】

      域名和域名对应IP地址【http://www.test.com    http://37.254.15.10】

      主域相同不同子域【http://www.test.com   http://test.com  http://script.test.com】 

    3.跨域出现的场景?

      一个应用需要请求不同(服务主机 / 域名不同->不同源)的服务接口

    4.跨域会限制什么?

      Cookie、LocalStorage 和 IndexDB 无法读取

      DOM 和 JS 对象无法获取

      Ajax请求发送不出去

    解决方案

    1.CORS

      Cors:全称是"跨域资源共享"(Cross-origin resource sharing)它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

       【需要浏览器和服务器同时支持, IE10以上浏览器均支持。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉, 实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信】

      【值得注意的是,通常使用CORS时,异步请求会被分为简单请求和非简单请求,非简单请求的区别是会先发一次预检请求。

      

    【非简单请求】

    1. 使用了下面任一 HTTP 方法:
    • PUT
    • DELETE
    • CONNECT
    • OPTIONS
    • TRACE
    • PATCH
    1. 人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (but note the additional requirements below)
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width

    - 仅当POST方法的Content-Type值等于下列之一才算作简单请求 - text/plain - multipart/form-data - application/x-www-form-urlencoded

      

      Nginx设置

    add_header 'Access-Control-Max-Age' 86400;
    add_header Access-Control-Allow-Origin *;//重点
    add_header Access-Control-Allow-Credentials true;
    add_header Access-Control-Allow-Methods GET,POST,OPTIONS,DELETE,PUT;
    add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
    

    2.反向代理  

      Nginx反向代理 通过把非同源请求用同源代理的方式来饶过跨域限制。

    proxy_pass http://www.test.com/
    

    3.JSONP

      JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。

      JSONP是JSON with Padding的略称。它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)

      凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>

      web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。

         Jquery 在每次跨域发送请求时都会有callback这个参数,其实这个参数的值就是回调函数名称,所以,服务器端在发送json数据时,应该把这个参数放到前面,这个参数的值往往是随机生成的,如:jsonp1294734708682,同时也可以通过 $.ajax 方法设置 jsonpcallback 方法的名称

    <script type="text/javascript">
        // 得到航班信息查询结果后的回调函数
        var flightHandler = function(data){
            alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
        };
        // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
        var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
        // 创建script标签,设置其属性
        var script = document.createElement('script');
        script.setAttribute('src', url);
        // 把script标签加入head,此时调用开始
        document.getElementsByTagName('head')[0].appendChild(script); 
    </script>

    //原生的实现方式
    let script = document.createElement('script');

    script.src = 'http://www.nealyang.cn/login?username=Nealyang&callback=callback';

    document.body.appendChild(script);

    function callback(res) {
      console.log(res);
    }

      

    前端实现  【请求链接 http://localhost:3000/?callback=cbFnhhh

    $.ajax({
        url:'http://www.nealyang.cn/login',
        type:'GET',
        dataType:'jsonp',//请求方式为jsonp
        jsonpCallback:'callback',
        data:{
            "username":"Nealyang"
        }
    })
    

      

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>浏览器端js 模块测试</title>
        <script src="./require.js" defer async="true" data-main="main"></script>
        <script>
            function cbFn(data){
                console.log(data)
            }
        </script>
        <script src="http://localhost:3000/?callback=cbFn"></script>
    </head>
    <body>
        
    </body>
    </html>
    

      后端实现

    const http = require('http');
    const url = require('url');
    const hostname = '127.0.0.1';
    const port = 3000;   
    
    const data = {"name":"winyh"}
    
    const server = http.createServer((req, res) => {
      var params = url.parse(req.url, true);  
      res.statusCode = 200; 
      res.setHeader('Content-Type', 'text/plain');  
      if (params.query && params.query.callback) {
        console.log(params.query.callback)
        var str =  params.query.callback + '(' + JSON.stringify(data) + ')';//jsonp  
        res.end(str);  
      } else {  
        res.end(JSON.stringify(data));//普通的json  
      }  
    });
    
    server.listen(port, hostname, () => {
        console.log(`Server running at http://${hostname}:${port}/`);
    });
    

      4.Server Proxy

    // 服务端代理请求代码
    // 服务端只是简单的通过正常的 HTTP 请求的方式来代理请求接口数据
    // 或者也可以使用 proxy 模块来代理,至于怎么使用 proxy 模块,待研究完善
    var url = 'https://cnodejs.org/api/v1/topics';        
    https.get(url, (resp) => {
        let data = "";
        resp.on('data', chunk => {
            data += chunk;
        });
        resp.on('end', () => {
            res.writeHead(200, {
                'Access-Control-Allow-Origin': '*',
                'Content-Type': 'application/json; charset=utf-8'
            });
            res.end(data);
        });
    })
    

      5.document.domain + iframe 跨域 

      【要求主域相同】

      6.websocket 协议跨域

      7.Node代理跨域

      8.location.hash + iframe 跨域 ?

      9.window.name + iframe 跨域 ?

      10.document.domain + iframe 跨域 ?

    比较

      协议,域名,端口号不相同的资源之间相互通信,就会产生跨域问题。

      处于安全考虑,浏览器的同源策略限制了不同域之间相互通信。

      JSONP,CORS,Server Proxy 跨域解决方式的应用场景都是用于前后端之间的数据通信,其他跨域解决方案主要是解决窗口页面之间的数据通信。

      JSONP 只支持 GET 方式的 HTTP 请求。

      CORS 跨域资源请求需要后端支持。

      Server Proxy 直接让后端代理发送请求。

      CORS对浏览器有要求,但对前后端的技术实现无改变

      JSONP对浏览器没有要求,但其最终是通过GET方法访问服务,限制了数据大小,并且对服务端技术实现有很大依赖

      反向代理对浏览器和技术实现均无要求,但限制了部署的灵活性

  • 相关阅读:
    音频,视频简单运用
    转载:Linux Used内存到底到哪里去了?
    shell awk统计重复个数
    Java中的单例模式
    Grub启动配置文件
    C语言实现全排列
    C语言缓冲区清空
    c语言内存对齐(1)
    防盗链原理
    C语言内存对齐(2)
  • 原文地址:https://www.cnblogs.com/winyh/p/10721333.html
Copyright © 2020-2023  润新知