zoukankan      html  css  js  c++  java
  • 浏览器同源策略和跨域的实现方法

    目录

    同源策略

    跨域资源共享(CORS)

    跨域的实现方法

    1、降域 document.domain

    2、JSONP跨域

    3、CORS跨域


    同源策略

    同源策略(Same Origin Policy,SOP)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
    所谓同源是指域名,协议,端口相同。
    当一个浏览器的两个tab页中分别打开百度和谷歌的页面时,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。 如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以google.com下的js脚本采用ajax读取baidu.com里面的文件数据是会报错的。

    如何判断是否是同源,可以查看该表

    不受同源策略限制的:

    • 页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
    • 跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的<script src="..."></script>,<img>,<link>,<iframe>等 

    比如下面的代码,我们访问 192.168.10.14下的一个文件,然后用js读取其数据,显示在页面上

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Ajax</title>
        <script type="text/javascript">
            function foo(){
                var xmlhttp=new XMLHttpRequest();
                xmlhttp.open("GET","http://192.168.10.14/1.txt",true);
                xmlhttp.send();
                xmlhttp.onreadystatechange=function()
                {
                    if (xmlhttp.readyState==4 && xmlhttp.status==200)
                    {
                        document.getElementById("my").innerHTML=xmlhttp.responseText;  
                    }
                }
            }
        </script>
    </head>
    <body>
        <button id="btn" οnclick="foo()">确定</button>
        <p id="my">hello,word!</p>
    </body>
    </html>

     当点击确定按钮读取 http://192.168.10.14/1.txt 的内容,并替换 hello,word! 的时候,发生了如下错误。这就是跨域请求错误!

    跨域的实现

    跨域资源共享(Cross Origin Resourse-Sharing):受前面所讲的浏览器同源策略的影响,不是同源的脚本不能操作其他源下面的对象。想要操作另一个源下的对象是就需要跨域。

    跨域的实现方法

    1、降域 document.domain

    同源策略认为域和子域属于不同的域,如:
    child1.a.com 与 a.com,
    child1.a.com 与 child2.a.com,
    abc.child1.a.com 与 child1.a.com 
    两两不同源,但是可以通过设置 document.domain='a.com',浏览器就会认为它们都是同一个源。想要实现以上任意两个页面之间的通信,两个页面必须都设置documen.domain='a.com'。
    此方式的特点:

    • 只能在父域名与子域名之间使用,且将 xxx.child1.a.com域名设置为a.com后,不能再设置成child1.a.com
    • 存在安全性问题,当一个站点被攻击后,另一个站点会引起安全漏洞
    • 这种方法只适用于 Cookie 和 iframe 窗口

    2、JSONP跨域

    JSONP 是 JSON With Padding(填充式 JSON 或参数式 JSON)的简写。

    JSONP实现跨域请求的原理:简单的说,就是动态创建<script>标签,然后利用<script>的 src 属性不受同源策略约束来跨域获取数据。

    JSONP 由两部分组成:回调函数 数据。回调函数是用来处理服务器端返回的数据,回调函数的名字一般是在请求中指定的。而数据就是我们需要获取的数据,也就是服务器端的数据。

    JSONP在不同的语言中有不同的实现方法,以下只展示在html中的简单实现过程。

    JSONP的简单实现过程

    举例:如果 a.com/abc.html 想得到 b.com/1.txt 中的数据,首先在abc.html中创建一个回调函数handleResponse,用来处理服务器端返回的数据。然后在abc.html中创建一个函数 foo,该函数的功能是动态添加<script>标签,src属性向服务器发送请求,请求地址为http://b.com/1.txt。然后在服务器端的请求数据1.txt中设置这个回调函数为handleResponse,并且以JSON数据形式作为参数传递,完成回调。我们来看看代码:

    a.com/abc.html的代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>JSONP实现跨域</title>
        <script type="text/javascript">
            function handleResponse(response){   //处理服务器返回的数据
                console.log(response);    //控制台输出
            }
            function foo() {
                var script = document.createElement("script");
                script.src = "http://192.168.31.122/1.txt"; //设置请求的链接以及处理返回数据的回调函数
                document.body.insertBefore(script, document.body.firstChild);
            }
        </script>
    </head>
    <body>
    <button id="btn" οnclick="foo()">确定</button>
    </body>
    </html>

    192.168.10.14/1.txt 的代码,设置回调函数,数据以JSON格式存放

    handleResponse([ { "name":"xie",
        "sex" :"man",
        "id" : "66" },
      { "name":"xiao",
        "sex" :"woman",
        "id" : "88" },
      { "name":"hong",
        "sex" :"woman",
        "id" : "77" }]
    )

    然后当我们点击了 确定按钮后,console控制台就输出了从192.168.10.14/1.js  传过来的JSON格式的数据了

     采用jsonp跨域也存在问题:

    • 使用这种方法,只要是个网站都可以拿到b.com里的数据,存在安全性问题。目前已知的有Referer校验和Token校验。
    • 只能是GET,不能POST
    • 可能被注入恶意代码,篡改页面内容,可以采用字符串过滤来规避此问题

    3、CORS跨域资源共享

    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
    它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。使用AJAX技术跨域获取数据
    刚才的例子中,用CORS实现跨域。
    在b.com里面添加响应头声明允许a.com的访问,代码

    Access-Control-Allow-Origin: http://a.com

    然后a.com就可以用ajax获取b.com里的数据了。
    注意:此方法IE8以下完全不支持,IE8-10部分支持。详见:caniuse-CORS

    还有一些其他的方法可以实现跨域请求数据:

    • HTML5的postMessage方法
    • window.name
    • location.hash

    相关文章:异步访问技术Ajax(XMLHttpRequest)

  • 相关阅读:
    团队作业第五次—项目冲刺-Day6
    团队作业第五次—项目冲刺-Day4
    团队作业第五次—项目冲刺-Day3
    团队作业第五次—项目冲刺-Day2
    研途——冲刺集合
    团队作业第六次—事后诸葛亮
    研途——测试总结
    研途——冲刺总结
    研途——冲刺日志(第七天)
    研途——冲刺日志(第六天)
  • 原文地址:https://www.cnblogs.com/csnd/p/11807974.html
Copyright © 2011-2022 走看看