js里的同源

JavaScript015

js里的同源,第1张

/*------------同源---------------*/

同源:当两个接口的协议、域名、端口号都相等时,这俩接口是同源的,只要有一个条件不相等,则非同源。不是同源的两个页面不能互相访问本地缓存、不能互相修改dom节点、不能使用ajax请求对方接口数据

如何判断两个网页同源

1、协议相同       2、域名相同          3、端口号相同

同源策略目的:1、保护本地缓存不被读取2、保护网站不被其他网站修改

同源策略的限制:

1、Cookie、localStorage、indexDB无法读取

2、dom节点无法获得。

3、AJAX请求无法发送。

JSONP:利用scritp标签请求外部服务器中的数据,从而绕开同源策略对AJAX请求数据的限制。

jsonp的本质:利用script标签中src属性可以加载任意文件的特性,通过这个属性来访问数据接口(添加一个回调函数作为参数),而数据接口会返回一个由回调函数名包裹的json数据,从而达到获取跨域数据的目的。

/*------------封装JSONP---------------*/

creatScriptTag('http://10.0.159.198/data.php?callback=abc')

function abc (data) {

alert(data)

}

ajax和jsonp其实本质上是不同的东西。

ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加标签来调用服务器提供的js脚本。

            在vue中,我们使用component内置组件或者vue-router切换视图的时候,由于vue会主动卸载不使用的组件,所以我们不能保存组件之前的状态,而我们经常能遇到需要保存之前状态的需求,例如:搜索页(保存搜索记录),列表页(保存之前的浏览记录)等等。

            Keep-alive是一个vue的内置组件,它能将不活动的组件保存下来,而不是直接销毁,当我们再次访问这个组件的时候,会先从keep-alive中存储的组件中寻找,如果有缓存的话,直接渲染之前缓存的,如果没有的话,再加载对应的组件。

            作为抽象组件,keep-alive是不会直接渲染在DOM中的。

        Keep-alive提供了三种可选属性

        Include-字符串或数组或正则表达式。只有名称匹配的组件被缓存。

        Exclude -字符串或数组或正则表达式。名称匹配的组件不会被缓存。

        Max -数字类型。表示最多可以缓存多少组件实例。

        Keep-alive提供了两个生命钩子,分别是activated与 deactivated。

        因为Keep-alive会将组件保存在内存中,并不会销毁以及重新创建,所以不会重新调用组件的created等方法,需要用activated与deactivated这两个生命钩子来得知当前组件是否处于活动状态。

        V-show有较高的渲染成本,

        V-if有较高的切换成本。

        V-if是真正的条件渲染,确保切换过程中条件内的事件监听器和子组件适当的被销毁和重建。

        V-show的元素始终被渲染并保存在dom中,操作的只是display属性控制演示影藏。

        源(origin)—— 就是协议、域名和端口号。若地址里面的协议、域名和端口号均相同则属于同源。

        同源策略——同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。

    不受同源策略限制的

            1.页面中的链接,重定向以及表单提交是不会受到同源策略限制的。

            2.跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的<script src="..."></script>,<img>,<link>,<iframe>等。

      跨域——只要协议、域名、端口号有一个不同就是跨域。

        跨域的原因?(只做了解)

跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号(如存在)相同,则允许相互访问。为了防止某域名下的接口被其他域名下的网页非法调用,是浏览器对JavaScript施加的安全限制。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是针对JS和ajax的,html本身没有跨域问题,比如a标签、script标签、甚至form标签(可以直接跨域发送数据并接收数据)等。

       1、 Jsonp——

                利用script标签可跨域的特点,在跨域脚本中可以直接回调当前脚本的函数。jsonp是一种常用的跨域手段,和反向代理,服务端做跨域处理相比,jsonp更显得方便轻巧 jsonp的缺点只能发送get请求。因为script只能发送get请求需要后台配合。此种请求方式应该前后端配合,将返回结果包装成callback(result)的形式。

       2、 Cors——

                服务器设置HTTP响应头中Access-Control-Allow-Origin值,解除跨域限制。CORS 是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing),他允许浏览器向跨源服务器发送XMLHttpRequest请求,从而克服 AJAX 只能同源使用的限制

                缺点是:目前所有最新浏览器都支持该功能,但是万恶的IE不能低于10

Access-Control-Allow-Origin 这个字段是必须的,表示接受那些域名的请求(*为所有)、Access-Control-Allow-Credentials 该字段可选, 表示是否可以发送cookie、Access-Control-Expose-Headers 该字段可选,XHMHttpRequest对象的方法只能够拿到六种字段: Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma ,如果想拿到其他的需要使用该字段指定。

       3、反向代理(Reverse Proxy){前端独立就能解决的跨域方案}——

    指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。

    

1、同源策略

同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。这个策略可以追溯到 Netscape Navigator 2.0。

Mozilla 认为两个页面拥有相同的源,如果它们的协议、端口(如果指明了的话)和主机名都相同。下表给出了相对http://store.company.com/dir/page.html同源检测的结果:

URL 结果 原因

http://store.company.com/dir2/other.html 成功

http://store.company.com/dir/inner/another.html 成功

https://store.company.com/secure.html 失败 协议不同

http://store.company.com:81/dir/etc.html 失败 端口不同

http://news.company.com/dir/other.html 失败 主机名不同

同源策略,简单地说就是要求动态内容(例如,JavaScript或者VBScript)只能阅读与之同源的那些HTTP应答和cookies,而不能阅读来自不同源的内容。更为有趣的是,同源策略对写操作没有任何限制。

2、JSONP

以上同源策略是基于安全考虑的,当前域不能访问其他域的东西。但这也带来一个问题,不同域之间如何协助。

先看一个简单的不同源请求的例子。准备2段代码,用来模拟2个不同源的服务器,分别部署在2个不同的web容器上。为了方便,我们直接使用jquery进行异步请求,不使用原生的 XMLHttpRequest.

localfile.html

Html代码 收藏代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>

<head>

<title></title>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>

<body>

<script type="text/javascript">

$(document).ready(function () {

$.get('./sayhello.js', function(result) {})

$.get('http://freeyun.duapp.com/jsonp/sayhello.js', function(result) {})

})

</script>

</body>

</html>

sayhello.js

Js代码 收藏代码

alert("hello jsonp")

这两个文件同时放到一个远程的服务器freeyun.duapp.com和本机的容器localhost的容器上。

在本机访问http://localhost:8080/jsonp/localfile.html,我们只能看到一个 hello jsonp的提示框。

通过F12打开chrome流程器的调试窗口,刷新,在network一栏可以看到如下信息:

对于远程服务器的请求出错了。

在console栏可以看到出错信息为:

XMLHttpRequest cannot load http://freeyun.duapp.com/jsonp/sayhello.js. Origin http://localhost:8080 is not allowed by Access-Control-Allow-Origin.

这个也就是因不同源导致了一个跨域请求失败。

那怎么解决这个问题呢?你一定发现了刚刚我们localfile.html里对jquery的引用,script标签里src属性里的jquery路径和我们的本地服务器并不是同源的,也就是说script标签里的src属性里的路径不受同源策略的限制的。

我们修改一下localfile.html

Html代码 收藏代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>

<head>

<title></title>

<script type="text/javascript" src="http://freeyun.duapp.com/jsonp/sayhello.js"></script>

</head>

<body>

</body>

</html>

重新访问localfile.html,这样依然会弹出 hello jsonp 的提示框,也就是说我们能过本地服务器访问到的远程服务器信息。

Html代码 收藏代码

通过script标签的开放策略,抓到的资料并不是 JSON,而是任意的 JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。

JSON只是一种数据描述格式,究竟是JSONP还是其他的“XXP”、“YYP”其实只是2个不同源的服务器之间的数据交换采用什么样的格式而已。

因为跨域的请求主要是为了能从别的服务器上获取数据,那么一般在数据获取完成后本地服务器都会做相应的数据处理,所以在JSONP这种模式里,会要求把返回结果放到本地一个回调函数中,这样就能直接通过本地回调方法对数据进行加工,这也就是我们常说的JSONP模式。