浏览器的同源策略与跨域处理

一、  同源策略

如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的

下表给出了相对http://store.company.com/dir/page.html同源检测的示例:

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。

允许跨源访问的一些例子:

  • <script src="..."></script> 标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。
  • <link rel="stylesheet" href="..."> 标签嵌入CSS。由于CSS的松散的语法规则,CSS的跨域需要一个设置正确的Content-Type 消息头。不同浏览器有不同的限制: IE, Firefox, Chrome, Safari (跳至CVE-2010-0051)部分 和 Opera。
  • <img>嵌入图片。支持的图片格式包括PNG,JPEG,GIF,BMP,SVG,...
  • <video> 和 <audio>嵌入多媒体资源。
  • <object><embed> 和 <applet> 的插件。
  • @font-face 引入的字体。一些浏览器允许跨域字体( cross-origin fonts),一些需要同源字体(same-origin fonts)。
  • <frame> 和 <iframe> 载入的任何资源。站点可以使用X-Frame-Options消息头来阻止这种形式的跨域交互。

使用 CORS 允许跨源访问。

跨源脚本API的访问

Javascript的APIs中,如 iframe.contentWindowwindow.parentwindow.open 和 window.opener 允许文档间直接相互引用。当两个文档的源不同时,这些引用方式将对 Window 和 Location对象的访问添加限制。

可以使用window.postMessage作不同源文档之间的交流。

跨源数据存储访问

存储在浏览器中的数据,如localStorageIndexedDB,以源进行分割。每个源都拥有自己单独的存储空间,一个源中的Javascript脚本不能对属于其它源的数据进行读写操作。

二、几种跨域解决方案

 1、JSONP

Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

Jsonp 的实现原理是利用 <script> 标签可以获取不同源资源的特点,来达到跨域访问某个资源的目的。假如 <script> 元素内部的代码没有位于某个函数中,那么这些代码会在页面被加载时被立即执行。

应用实例:

服务端代码使用jFinal框架

 1 package com.controller;
 2
 3 import com.mazu.core.Controller;
 4
 5 public class JsonPController extends Controller{
 6
 7     public void getUserInfo(){
 8
 9         String userId = getPara("userId");
10         String callBackFunc = getPara("callback");
11         if(userId!=null&&userId.equals("123")){
12             String userJson = "{\"userName\":\"Admin\",\"age\":26}";
13             callBackFunc += "(‘success‘,"+userJson+")";//拼接为callback(a,b)的形式返回给前端
14             renderJson(callBackFunc);
15         }else{
16             renderJson(callBackFunc+"(‘error‘)");
17         }
18     }
19 }

客户端代码

 1 <script>
 2 function callbackFunc(status,data){
 3     if(status=="success"){
 4         console.log(data.userName+":"+data.age);
 5     }else{
 6         console.log(status);
 7     }
 8 }
 9 </script>
10 <script type="text/javascript" src="http://localhost/TestJSONP/jsonp/getUserInfo?userId=123&callback=callbackFunc"></script>

chrome中执行结果

由于是本地测试,使用的是端口不同的两个项目,可以看到服务端响应后,返回给前端一个字符串callback(status,data),前端<script>接收到这段代码后立即执行,成功实现了跨域资源的访问。

在jQuery中如何通过JSONP来跨域获取数据

第一种方法是在ajax函数中设置dataType为‘jsonp‘:

$.ajax({
    dataType: ‘jsonp‘,
    url: ‘http://localhost/TestJSONP/jsonp/getUserInfo?userId=123‘,
    success: function(data){
       console.log(data);//success
    }
});

上面的方式只能返回一个参数,多参数时将无法得到第二个及之后的参数。

可以在传递过程中自定义函数名,使用jsonpCallback参数

jsonp:表示传递的参数,默认为callback,我们也可以自定义

jsonpCallback:表示传递的参数值,也就是回调的函数名称,这是自定义的名称

 1 <script src="http://apps.bdimg.com/libs/jquery/1.8.3/jquery.js"></script>
 2 <script>
 3 function callbackFunc(status,data){
 4     if(status=="success"){
 5        // console.log(data.userName+":"+data.age);
 6         console.log("callback:"+data);
 7     }else{
 8         console.log("callback:"+status);
 9     }
10 }
11 $.ajax({
12     type:"get",
13     url: ‘http://localhost/TestJSONP/jsonp/getUserInfo?userId=123‘,
14     dataType: ‘jsonp‘,
15     jsonp:‘callback‘,
16     jsonpCallback:‘callbackFunc‘,
17     success: function(data){
18        console.log("ajax:"+data);
19     }
20 });
21
22 </script>

执行结果:

可以看到返回结果中,仍然获取不到第二个参数值。仔细debug了一下后台,返回的字符串也是正确的。

于是我改了下后台的返回值和回调函数的参数,得到了正确的测试结果。

 由此可见,使用jQuery做JSONP跨域调用时,与ajax的success回调函数一样,服务端需要将传的内容封装在一个返回值中。

为什么使用jsonpCallback简单的绑定回调函数就能实现回调函数调用了呢?

仔细跟踪chrome中的执行过程,发现Jquery首先将回调函数赋值给一个内部函数,在服务端响应成功后,执行这个内部函数,然后销毁,起到一个临时代理的作用。

jQuery 的 $.ajax 只支持get方式获取跨域数据,并且它不支持出错时的回调。

jQuery-JSONP是一个支持 JSONP 调用的 jQuery 插件,使用它是因为它支持出错时的 ajax 回调。

 1 <script src="jquery-3.2.1.js"></script>
 2 <script src="jquery-jsonp.js"></script>
 3 <script>
 4     $.jsonp({
 5         url: ‘http://localhost/TestJSONP/jsonp/getUserInfo‘,
 6         data: { userId: 123 },
 7         callbackParameter: "callback",
 8         success: function (data, textStatus, xOptions) {
 9             console.log(data);
10         },
11         error: function (xOptions, textStatus) {
12         }
13     });
14 </script>

第1个需要注意的地方是 callbackParameter,如果没有专门的 callback 函数,一定要写上 "callback";
第2个需要注意的地方是在 success 回调函数中,xOptions包含传给服务器的参数,如xOptions.data={userId:123}。

2、CORS

CORS全称是“跨域资源共享”(Cross-origin resource sharing),它是一种通过设置HTTP头信息来获取跨源服务器上的特定资源,主要是设置Access-Control-Allow-Origin字段的值。

服务端代码:

 1 public void getUserInfo(){
 2
 3         String userId = getPara("userId");
 4         String userJson = "";
 5         if(userId!=null&&userId.equals("123")){
 6             System.out.println("userId:"+userId);
 7             userJson = "{\"userName\":\"Admin\",\"age\":26}";
 8         }
 9         //getResponse().setHeader("Access-Control-Allow-Origin", "*");
10         renderJson(userJson);
11
12     }

客户端代码:

1   $.ajax({
2       type:"get",
3       url: ‘http://localhost/TestJSONP/jsonp/getUserInfo?userId=123‘,
4       dataType: ‘json‘,
5       success: function(data){
6           console.log("ajax:"+data);
7       }
8   })

当服务端回应头信息中没有包含Access-Control-Allow-Origin字段时,浏览器报错如下:

设置Access-Control-Allow-Origin为*,表示接受任意域名的请求,在实际开发中为了安全起见一般设为特定域名。

与JSONP的比较

CORS与JSONP的使用目的相同,但是比JSONP更强大。

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

3、window.postMessage

HTML5跨文档消息传输Cross Document Messaging。下一代浏览器都将支持这个功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。

用postMessage支持基于web的实时消息传递。

window.postMessage() 方法被调用时,会在所有页面脚本执行完毕之后(e.g., 在该方法之后设置的事件、之前设置的timeout 事件,etc.)向目标窗口派发一个  MessageEvent 消息。

MessageEvent消息有四个属性需要注意:

  • message 属性表示该message 的类型;
  • data 属性为 window.postMessage 的第一个参数;
  • origin 属性表示调用window.postMessage() 方法时调用页面的当前状态;
  • source 属性记录调用 window.postMessage() 方法的窗口信息。

语法:

otherWindow.postMessage(message, targetOrigin, [transfer]);

参考:

原文地址:https://www.cnblogs.com/Youngly/p/8716424.html

时间: 2024-10-07 07:26:04

浏览器的同源策略与跨域处理的相关文章

浏览器的同源策略和跨域访问

1. 什么是同源策略 理解跨域首先必须要了解同源策略.同源策略是浏览器上为安全性考虑实施的非常重要的安全策略.    何谓同源:        URL由协议.域名.端口和路径组成,如果两个URL的协议.域名和端口相同,则表示他们同源.    同源策略:        浏览器的同源策略,限制了来自不同源的"document"或脚本,对当前"document"读取或设置某些属性.        从一个域上加载的脚本不允许访问另外一个域的文档属性. 举个例子:      

浏览器的同源策略及跨域解决方案

同源策略 一个源的定义 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源. 举个例子: 下表给出了相对http://a.xyz.com/dir/page.html同源检测的示例: URL 结果 原因 http://a.xyz.com/dir2/other.html 成功   http://a.xyz.com/dir/inner/another.html 成功   https://a.xyz.com/secure.html 失败 不同协议 ( https和http ) h

浏览器的同源策略和跨域问题

要理解跨域问题,必须得知道什么是同源策略. 什么是同源策略? 何谓同源:        URL由协议.域名.端口和路径组成. 如果两个URL的协议.域名和端口相同,则表示他们同源.同源策略:        浏览器的同源策略,限制了来自不同源的"document"或脚本,对当前"document"读取或设置某些属性.         从一个域上加载的脚本不允许访问另外一个域的文档属性. 举个例子:        比如一个恶意网站的页面通过iframe嵌入了银行的登录页

ajax请求总是不成功?浏览器的同源策略和跨域问题详解

场景 码农小明要做一个展示业务数据的大屏给老板看,里面包含了来自自己网站的数据和来自隔壁老王的数据.那么自己网站的数据提供了 http://xiaoming.com/whoami 这样的数据接口隔壁老王提供了 http://oldwang.com/isdad 这样的数据接口单独点开都是没有问题的.但是一使用 js 的 ajax 请求就无法收到来自 oldwang.com 的数据了.点开浏览器控制台一看,红字标出(Chrome): XMLHttpRequest cannot load http:/

同源策略和跨域-总结

目录: 1.同源策略 2.跨域 3.几种跨域技术 1.同源策略 什么叫同源? URL由协议.域名.端口和路径组成,如果两个URL的协议.域名和端口相同,则表示他们同源.相反,只要协议,域名,端口有任何一个的不同,就被当作是跨域. e.g. 对于http://store.company.com/dir/page.html进行同源检测: URL 结果 原因 http://store.company.com/dir2/other.html 成功 仅路径不同 http://store.company.c

JS同源策略和跨域访问

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现. 1. 什么是同源策略 理解跨域首先必须要了解同源策略.同源策略是浏览器上为安全性考虑实施的非常重要的安全策略. 何谓同源: URL由协议.域名.端口和路径组成,如果两个URL的协议.域名和端口相同,则表示他们同源. 同源策略: 浏览器的同源策略,限制了来自不同源的"doc

第二百七十四节,同源策略和跨域访问

同源策略和跨域访问  什么是同源策略 尽管浏览器的安全措施多种多样,但是要想黑掉一个Web应用,只要在浏览器的多种安全措施中找到某种措施的一个漏洞或者绕过一种安全措施的方法即可.浏览器的各种保安措施之间都试图保持相互独立,但是攻击者只要能在出错的地方注入少许JavaScript,所有安全控制几乎全部瓦解--最后还起作用的就是最弱的安全防线:同源策略.同源策略管辖着所有保安措施,然而,由于浏览器及其插件,诸如Acrobat Reader.Flash 和Outlook Express漏洞频出,致使同

同源策略和跨域访问

1. 什么是同源策略 理解跨域首先必须要了解同源策略.同源策略是浏览器上为安全性考虑实施的非常重要的安全策略.     何谓同源:         URL由协议.域名.端口和路径组成,如果两个URL的协议.域名和端口相同,则表示他们同源.     同源策略:         浏览器的同源策略,限制了来自不同源的"document"或脚本,对当前"document"读取或设置某些属性. (白帽子讲web安全[1])         从一个域上加载的脚本不允许访问另外一

同源策略与跨域访问

1. 什么是同源策略 理解跨域首先必须要了解同源策略.同源策略是浏览器上为安全性考虑实施的非常重要的安全策略.    何谓同源:        URL由协议.域名.端口和路径组成,如果两个URL的协议.域名和端口相同,则表示他们同源.    同源策略:        浏览器的同源策略,限制了来自不同源的"document"或脚本,对当前"document"读取或设置某些属性. (白帽子讲web安全[1])        从一个域上加载的脚本不允许访问另外一个域的文档