美文网首页
同源政策

同源政策

作者: Camilia_yang | 来源:发表于2019-08-25 14:24 被阅读0次

    "同源政策"是浏览器安全的基石。

    含义

    它最初的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。

    “同源”的概念

    "同源"指的是"三个相同":协议相同 、域名相同、端口相同

    http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)。
    它与http://example.com/dir/other.html不同源,其域名不同(只是一级域名相同)。

    同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。

    限制范围

    如果非同源,共有三种行为受到限制。

    1. Cookie、LocalStorage 和 IndexDB 无法读取。
    2. DOM 无法获得。
    3. AJAX 请求不能发送。

    同源政策的规避

    Cookie

    服务器在设置Cookie的时候,指定Cookie的所属域名为一级域名,比如.example.com。
    Set-Cookie: key=value; domain=.example.com; path=/
    这样的话,二级域名和三级域名不用做任何设置,都可以读取这个Cookie。
    提醒:
    前端最好不要随意去设置cookie,因为cookie信息量太大会影响到请求和响应的速度,所以最好统一由后端去设置。

    iframe

    如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和window.open方法打开的窗口,它们与父窗口无法通信。
    父窗口运行下面的命令,如果iframe窗口不是同源,就会报错。

    document.getElementById("myIFrame").contentWindow.document`
    // Uncaught DOMException: Blocked a frame from accessing a cross-origin frame.
    

    反之亦然,子窗口获取主窗口的DOM也会报错。

    window.parent.document.body
    // 报错
    

    对于完全不同源的网站,目前有三种方法,可以解决跨域窗口的通信问题。

    • 片段识别符(fragment identifier)
    • window.name
    • 跨文档通信API(Cross-document messaging)

    AJAX

    同源政策规定,AJAX请求只能发给同源的网址,否则就报错。
    除了架设服务器代理,有三种方法规避这个限制。

    • JSONP
    • WebSocket
    • CORS

    JSONP
    JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。

    它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。

    首先,网页动态插入<script>元素,由它向跨源网址发出请求。

    function addScriptTag(src) {
      var script = document.createElement('script');
      script.setAttribute("type","text/javascript");
      script.src = src;
      document.body.appendChild(script);
    }
    
    window.onload = function () {
      addScriptTag('http://example.com/ip?callback=foo');
    }
    
    function foo(data) {
      console.log('Your public IP address is: ' + data.ip);
    };
    

    上面代码通过动态添加<script>元素,向服务器example.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字,这对于JSONP是必需的。

    服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。

    foo({
      "ip": "8.8.8.8"
    });
    

    由于<script>元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,因此避免了使用JSON.parse的步骤。

    WebSocket
    WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
    下面是一个例子,浏览器发出的WebSocket请求的头信息

    
    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
    Sec-WebSocket-Protocol: chat, superchat
    Sec-WebSocket-Version: 13
    Origin: http://example.com
    
    

    上面代码中,有一个字段是Origin,表示该请求的请求源(origin),即发自哪个域名。服务器可以根据这个字段,判断是否许可本次通信。如果该域名在白名单内,服务器就会做出回应。

    CORS
    什么是 CORS:Cross-Origin Resource Sharing(跨域资源共享)
    比如,a.com的前端向b.com的服务器发请求
    request.open('GET', 'http://b.com:8002/ada')
    会报错了,因为不是同源,响应完成却得不到任何内容
    解决方法,在Node代码中加入一句

    //允许 http://ada.com:8001 访问我
    response.setHeader('Access-Control-Allow-Origin','http://ada.com:8001')
    

    这就是用CORS实现AJAX跨域的过程

    参考资料:
    http://www.ruanyifeng.com/blog/2016/04/cors.html

    相关文章

      网友评论

          本文标题:同源政策

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