如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的 源 。
举个例子:
下表给出了相对 http://a.bbb.com/dir/page.html 同源检测的示例:
由同源策略导致的的AJAX请求失败
例如:页面路径为: http://127.0.0.1:8848/fileTest/test.html
后台接口地址为: http://localhost:8080/sayHello
产生的结果:
此即为跨域请求失败
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了AJAX只能 同源 使用的限制。
在此之前,需要知道 简单请求、复杂请求
简单请求:
某些请求不会触发 CORS 预检请求 。本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。若请求满足所有下述条件,则该请求可视为“简单请求”:
复杂请求:
与前述简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。当请求满足下述任一条件时,即应首先发送预检请求:
若需要跨域,则需要在请求头里添加 Origin 字段
请求至后台若符合后台请求规则则可成功请求,并且后台会返回相应的规则
当请求为复杂请求时,浏览器会在请求前先发送一个 OPTIONS 请求
OPTIONS 是一个预检请求,与简单请求不同的是它会额外携带两个参数: Access-Control-Request-Method :该次请求的请求方式 Access-Control-Request-Headers :该次请求的自定义请求头字段
OPTIONS 发送至后台若后台成功响应,则继续发送复杂请求,若响应失败则不会发送复杂请求
继续发送复杂请求
(1)、OPTIONS不会携带body若后台方法上使用@RequestBody注解,则会报错:
例如:
此时需要在@RequestBody后添加参数required=false,允许body为空
即可解决该问题
(2)、OPTIONS请求不应被过多的发送,因为它也是一个http请求也会占用一部分资源,相应的一种解决方法
在响应中添加缓存字段,以减少OPTIONS请求
(1)、在Java web工程中加如下列过滤器即可
(2)、在nginx中配置
使用反向代理工具解决跨域问题:如 Nginx 、 node.js
以Nginx为例:
在Nginx的配置文件中加入:
启动Nginx再以
http://127.0.0.1/fileTest/test.html 地址访问页面
http://127.0.0.1/sayHello 访问后台接口
发现可正常请求
上述以
http://127.0.0.1/fileTest/test.html 地址访问页面
http://127.0.0.1/sayHello 访问后台接口
的方式遵循了,浏览器的同源策略自然不存在跨域
Nginx代理了页面请求和接口请求,所以页面请求和接口请求都在Nginx源内由Nginx去完成页面请求和接口的请求即: http://127.0.0.1:80 内
所以浏览器访问页面和接口都是以 http://127.0.0.1:80 来进行访问的,满足了同源策略自然不存在跨域之说
图解:
跨域:
Nginx代理,满足同源策略
Nginx反向代理其实是一种欺骗浏览器的方法
[1] http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html 浏览器同源政策及其规避方法
[2] http://www.ruanyifeng.com/blog/2012/09/xmlhttprequest_level_2.html XMLHttpRequest Level 2 使用指南
[3] http://www.ruanyifeng.com/blog/2016/04/cors.html 跨域资源共享 CORS 详解
[4] https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS HTTP访问控制(CORS)
在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上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)