1、域名(二级域名与一级域名之间也算是不同源)
2、端口
3、协议
浏览器基于用户的隐私安全目的,防止恶意网站窃取数据(只是浏览器有这个同源策略设置,但是用命令行curl请求某个跨域地址时能得到相应结果),不允许不同域名的网站之间互相调用ajax XHR对象, 只是不允许XHR对象,对其他的图片、js 脚本、css 脚本还是可以通过标签跨域调用。
所以 css/js/img 可以跨域请求(即引用),AJAX 不能请求跨域的资源。
同源策略会限制以下三种行为:
JSONP(json with padding)方式, 通过 script标签请求资源,允许用户在 src 地址中传递一个 callback 参数(callback=abc)即将预先定义好的回调函数名以查询字符串的形式传递给服务端,服务端收到请求后会将要返回的数据用这个callback参数(abc)包裹住再返回,即将请求传入的参数 abc 作为函数名来包裹住要返回的 JSON 数据,比如 abc(JSON),这样客户端在收到服务端返回的abc(JSON)文件后默认用JS解析执行。通过JSONP就可以随意定制自己的函数来自动处理返回数据了。
虽然浏览器默认禁止了跨域访问,但并不禁止在页面中 script 标签引用其他域下的 JS 文件,比如线上 jquery 库,并可以自由执行引入的 JS 文件中的 function(包括操作 cookie、Dom 等等)。
根据这一点,可以方便地通过动态创建script节点的方法来实现完全跨域的通信。
1、安全问题,src 引用是开放的,所以 jsonp 的资源都被所有人访问到。解决方法是用 jsonp 中的 token 参数,通过A域和B域共用同一套 cookie 来验证A的身份。
2、只能用GET方式不能用POST方式获取数据因为是基于 src 引用的,引用是 get 请求。 3、可被注入恶意代码如 ?callback=alert(1),这问题只能用正则过滤字符串的方法解决,过滤 callback 后的内容不能有括号之类的条件
1.定义数据处理函数
appendHtml(){
xxxxx
}
2、创建 script 标签,src 的地址执行后端接口,最后加个参数 callback=appendHtml。如:
var script=document.createElement('script')
script.src="http://127.0.0.1/getNews?callback=appendHtml"
3、服务端在收到请求后,解析参数,计算返还数据,输出 appendHtml(data) 字符串。 4.前台页面收到服务端返回的 appendHtml(data) 字符串所构建的 script 标签,页面加载这个 script 标签时做为 js 执行。 此时会调用 appendHtml()函数,将 data 做为参数。
注意:JSONP 实现的前提是后端必须有 JSONP 的 API 接口,即后端有将前端传入的参数作为函数名包裹数据返回 js 文件的逻辑。
CORS允许浏览器向跨域服务器发出 XMLHttpRequest 请求,突破了 AJAX 只能同源使用的限制。CORS 需要浏览器和服务器同时支持,目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。CORS原理:浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。只要服务器实现了 CORS 接口,就可以跨源通信。
header("Accept-Control-Allow-Origin","*")//允许所有源发起的请求
如果 Origin 指定的源,不在服务端许可范围内,服务器会返回一个正常的 HTTP 回应。
但这个响应头信息没有包含 Access-Control-Allow-Origin 字段。
浏览器接收后就知道出错了,从而抛出一个错误,被 XMLHttpRequest 的 onerror 回调函数捕获。
这种错误无法通过状态码识别,因为 HTTP 回应的状态码有可能是 200。
如果Origin指定的域名在许可范围内,服务器返回的响应,响应头会包含以下信息字段
Access-Control-Allow-Origin: http://api.a.com
// 允许来自源 http://api.a.com 的访问,如果是*则代表允许来自所有源的访问
HTML5 中最酷的新功能之一就是 跨文档消息传输 Cross Document Messaging。
下一代浏览器都将支持这个功能。Facebook 已经使用了这个功能,用 postMessage 支持基于 web 的实时消息传递。
举例,父窗口 aaa.com 向子窗口 bbb.com 发消息,调用 postMessage 方法如下:
var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');
// 第一个参数是具体的信息内容(支持任意类型),
// 第二个参数是接收消息目标窗口的源origin(协议 + 域名 + 端口)也可以设为*,表示不限制域名,向所有窗口发送。
子窗口向父窗口发送消息的写法如下:
window.opener.postMessage('Nice to see you', 'http://aaa.com');
父窗口和子窗口都可以通过message事件,监听对方的消息:
window.addEventListener('message', function(event) {
console.log(e.data);
},false);
当两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置 document.domain 来实现 iframe 窗口相互访问或设置 cookie。降域方式只适用于同一站点下不同子域名共享 cookie 或者 iframe 页面中嵌套的子域名页面之间的访问。降域不适用访问 LocalStorage 和 IndexedDB,postMessage() 方法可访问 LocalStorage。
举例来说,A网页是 http://w1.example.com/a.html ,B网页是 http://w2.example.com/b.html ,子域名不同默认情况下会被同源策略阻止访问。只要将两个页面都设置相同的 document.domain,两个网页就可以共享 Cookie 或在 iframe 窗口下相互访问。
document.domain = 'example.com';
服务器也可以在设置 Cookie 的时候,指定 Cookie 的所属域名为一级域名以后二级域名和三级域名不用做任何设置,都可以读取这个 Cookie。比如 .example.com。
Set-Cookie: key=value; domain=.example.com; path=/
