zoukankan      html  css  js  c++  java
  • 跨域问题与解决方案

    跨域

    制定HTML规则时,出于安全的考虑,一个源的网站不允许与另一个源的资源进行交互,浏览器制定此规则为同源策略

    同源即指的网站具有相同的域,即 协议(protocol)、主机(host)、端口号(port) 相同。

    跨域资源嵌入是允许的,但是浏览器限制了Javascript不能与加载的内容进行交互,如嵌入的<script>、<img>、<link>、<iframe>等。

    受限的场景

    • XHR请求不能发送。
    • 无法对跨域请求的资源进行修改。
    • 不同源的CookieLocalStorage无法读取。

    跨域解决方案

    JSONP跨域请求数据

    由于<script>可以对跨域资源进行请求,于是可以对DOM动态地append一个<script>并添加src且携带一个callback函数名,待请求完成后调用callback

    //前端
    function jsonpHandle(data){console.log(data);} //首先定义函数,请求完成后会携带参数调用函数
    var url = "http://127.0.0.1/test.php?callback=jsonpHandle";
    var obj = $('<script><\/script>');
    obj.attr("src",url);
    $("body").append(obj); // 动态地添加一个script
    
    // 后端配合实现
    $data = ["a" => 1, "b" => 2];
    $callback = $_GET['callback'];
    return $callback."(".json_encode($data).")";
    

    CORS跨域

    对于简单请求,浏览器会直接发送CORS请求,具体说来就是在header中加入origin请求头字段。同样,在响应头中,返回服务器设置的相关CORS头部字段,Access-Control-Allow-Origin字段为允许跨域请求的源。请求时浏览器在请求头的Origin中说明请求的源,服务器收到后发现允许该源跨域请求,则会成功返回。
    对于非简单请求,浏览器会自动先发送一个options请求,如果发现服务器支持该请求,则会将真正的请求发送到后端,反之,如果浏览器发现服务端并不支持该请求,则会在控制台抛出错误。

    //响应头 Response Headers
    header('Content-Type: text/html;charset=utf-8');
    header('Access-Control-Allow-Origin:http://localhost:8080'); // *代表允许任何网址请求
    header('Access-Control-Allow-Methods:POST,GET'); // 允许请求的类型
    header('Access-Control-Allow-Credentials: true'); // 设置是否允许发送 cookies
    header('Access-Control-Allow-Headers: Content-Type,Origin,Refer'); // 允许自定义请求头的字段 
    

    Nginx代理

    通过代理的手段,监听同一端口添加不同路径实现不同服务的跨域访问。

    location  /test
    {
        proxy_pass   http://127.0.0.1:81;
    }
    

    图片ping

    直接新建一个<img>,然后在地址中存放一些简单数据,这种方法只支持get请求,且只能单向地向服务器发送请求,在统计广告曝光次数中比较常见,XSS攻击也常用其获取cookie

    <img src="http://127.0.0.1?key=value">
    

    相同主域document.domain

    例如对于www.example.comabc.example.com,其主域名是一样的。

    document.domain = "example.com"; //相同主域
    var ifrWin = document.getElementById("ifr").contentWindow; //可以操作iframe
    

    window.name共享数据

    不同域的iframe把共享的信息放在window.name里面,此方法只适用于两个iframe之间的跨域。

    window.name = JSON.stringify({"a":1,"b":2})
    

    window.postMessage

    使用window.postMessage来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,这种方法不能和服务端交换数据。

    //主window
    window.frames[0].postMessage({"a":1},"http://127.0.0.1:81")
    //iframe //出于安全考虑验证来源
    window.addEventListener('message',(event)=>{
      if(event.origin === "http://127.0.0.1") console.log(event.data);
    });
    

    每日一题

    https://github.com/WindrunnerMax/EveryDay
    
  • 相关阅读:
    (单例)使用同步基元变量来检测程序是否已运行
    使用委托解决方法的跨线程调用问题
    Rtmp/Hls直播、点播服务器部署与配置
    关于C#调用广州医保HG_Interface.dll调用的一些总结(外部组件异常)
    redhat7.3配置163 yum源
    模块化InnoSetup依赖项安装
    [迷宫中的算法实践]迷宫生成算法——递归分割算法
    [新手学Java]使用beanUtils控制javabean
    【HTML5】Canvas绘图详解-1
    【Swift 】- 闭包
  • 原文地址:https://www.cnblogs.com/WindrunnerMax/p/12558306.html
Copyright © 2011-2022 走看看