跨域

(请求由封装好的jquery方法实现,后台由java实现)

Ⅰ.为什么会产生AJAX跨域问题?

产生跨域的三个条件:

  • 浏览器限制
  • 跨域(协议/域名/端口其中有不同的)
  • 使用XmlHttpRequest发送请求(使用其他的img的src,script的src,a标签的href等不会有该限制。

Ⅱ.基于以上原因解决思路

  • 浏览器限制(想办法让浏览器不去限制,可通过指定参数,不常用,玛法麻烦,需要客户端每个人的改动?)
  • XmlHttpRequest发送请求------->改用动态创建script,将调用的url赋予src属性。
  • 跨域(因为方法二jsonp有许多弊端,无法满足现在的开发要求,jsonp用的很少。
    基于跨域有两种解决思路:
    ①被调用方(支持跨域):基于http,服务端返回的响应首部字段里设置参数,告诉浏览器允许被访问,但是如果被调用方是其他公司,则无法修改,需要使用第二种思路
    ②调用方(隐藏跨域):通过代理。客户端a域名向b域名发送请求通过代理,将指定url(a域名)转为转为b域名。浏览器看上去就是同一个域名,不存在跨域问题了。

一.浏览器禁止检查

  • 命令行参数启动,通过指定一些参数,让浏览器不做校验。


    跨域_第1张图片

二.JSONP如何解决跨域问题

1.jsonp是什么?

(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。就是json使用方法的一种扩展。

2.使用jsonp服务端需要配合修改代码吗?

script标签返回的是js代码(script标签就是用来写js逻辑操作dom的,只是因为script标签的src没有跨域限制,所以以此来发送对url的请求,但请求返回的格式要符合script格式,为js代码。如果服务器不做任何改动,返回的还是一个json对象,所以浏览器会把服务器返回的json对象当作js代码来解析,所以会出错。
(不同的后台有不同的修改方式)


跨域_第2张图片
3. jsonp的实现原理?

跨域_第3张图片

①.type是不同的
跨域_第4张图片

②.返回类型不同,xhr返回json对象,script返回js脚本

跨域_第5张图片

③.url的不同
jsonp的url后面自动加了一长串,双击url之后,发现返回的是一段js代码。是一个函数的调用。一长串为函数名。我们所需的数据json对象是作为函数参数返回的。从这里可以发现jsonp的实现原理是发送url请求的时候加了参数,而后台发现了参数,就会知道这是一个jsonp请求,会把返回数据由json对象变为js代码,而js的内容就是一个函数调用
跨域_第6张图片

跨域_第7张图片

其中的callback就是客户端与服务端两边约定的一个参数。
jsonp不是一个官方协议。但是它也是一个协议,是两边约定好的。也就是说,如果服务端发现客户端发送过来的请求里参数名带了callback,那么认为这个请求为一个jsonp请求,那么返回的数据就不再是json对象,而是js代码。而js代码里函数调用的函数名为callback的值。要返回的json数据对象则作为函数的参数。这就是jsonp的实现原理。
跨域_第8张图片

3.JSONP有什么弊端

①服务器需要改动代码支持(如果要调用的是别人的服务器,那么自己就无法修改了,使用jsonp就是不可行的。)
②只支持get方法,因为是通过script标签发送请求的。试验一下,将客户端里请求时的参数类型type设置为post,请求成功后,检查相应类型,依然是get。设置无效。


跨域_第9张图片

跨域_第10张图片

③发送的不是XHR请求。因为xhr的api里封装了很多功能,比如异步,各种事件等,这些功能jsonp都没有。所以解决跨域的最好方式为基于跨域问题来解决。(分为服务端支持跨域和客户端隐藏跨域。)

最常见的JAVAEE架构

静态请求:如js文件,css文件,img图片等
动态请求:和用户有关的数据

当一个请求从浏览器发出去的时候,会先到中间的http服务器,或者叫静态服务器,中间的静态服务器收到请求之后,会判断这是静态请求还是动态请求。发现是静态请求的话,会直接处理,返回给客户端。如果是动态请求的话,会转发给后台的应用服务器(tomcat),tomcat处理完后会把请求返回给http服务器,http服务器再把请求转发给客户端浏览器。

可以看出,中间的http服务器至少起到两个作用:
①:处理静态请求
②:负载均衡


跨域_第11张图片

跨域的时候会有另外一个系统:


跨域_第12张图片
  • 思路一:直接从浏览器发出去请求,请求被调用方。这个时候要在被调用方上做相应的修改。这个修改是基于http协议跨域请求方面的规定。就是在返回头里增加一些字段,高速浏览器我这边允许对方调用,那么浏览器就不会报跨域问题了。
  • 思路二:隐藏跨域。这个时候的请求不是从浏览器发出,而是从中间的http服务器转出去。通过http服务器转发后,浏览器发现请求都是同一个域,就不会报跨域问题。这是调用方的http服务器来做修改的。

这两种方案可能修改的都是http服务器(配置),但是实现原理,思路是不一样的,要区分清楚。

三.跨域解决方向

  • 被调用方解决 (被调用方的http服务器修改配置)
  • 调用方解决(调用方的http服务器修改配置)
1.被调用方解决---支持跨域
跨域_第13张图片

由以上图片可以发现有三种方法可以实现
①http服务器(apache)
①http服务器(nginx)
②后台的应用服务器 (tomcat***重点)

被调用---filter解决方案(在响应头添加字段)
  • 浏览器先执行还是先判断?
    若不设置,在浏览器控制台中发现服务端其实已经成功返回数据,但是浏览器页面报错,无法加载内容,因为存在跨域问题。说明是先执行后判断。
  • 如何判断?
    可以对比普通请求和跨域请求的请求头区别。


    跨域_第14张图片

    可以发现跨域请求多了该字段。值是当前的域名信息。就是说,当浏览器发现请求为跨域请求时,会在该http请求头中加入当前域的请求字段。然后等相应返回后,就会检查返回的响应头里有没有允许该url跨域的信息。
    服务端设置响应头信息


简单请求和非简单请求
  • 是不是所有请求都是先执行后判断呢?
    ①简单请求:先执行后判断
    ②非简单请求:先发送一个预请求,再发送真正的请求


    跨域_第15张图片

试验一下:带json格式的ajax请求

跨域_第16张图片


发现只发送了一次预请求,没有发送第二次真正的请求。
跨域_第17张图片
询问后台是否允许该头访问
但是后台没有设置允许访问的信息,于是请求失败。

跨域_第18张图片
image.png

给服务端添加允许访问的头部信息。
跨域_第19张图片

此时请求成功。

Options预检命令
Options预检命令缓存
非简单请求每次都要发送两条请求很影响效率。
跨域_第20张图片

单位秒。在一个小时内如果再次请求相同信息,不用再次发送预请求。直接发送真正的请求。
因为浏览器把预检命令的结果缓存起来了。
跨域_第21张图片


此时如果把服务端对content-type的允许删去,客户端再次请求,依然是之发送一次,没有预请求,且请求数据显示成功,不会报错。如果删除浏览器的缓存,则会请求失败。

带cookie的跨域

需要注意两点:

  • 是被调用方的cookie,而不是调用方的cookie。 A发ajax请求给B, 带着的是B的cookie, 还是受限于同源策略, ajax的Request URL是B, cookie就是B的。cookie是加在被调用方的服务器中。比如请求的是8080端口,那就是将cookie加在8080端口的服务器中。因为只能读取本域的cookie。(自己的理解:浏览器会带上浏览器里的被调用域名下的cookie内容,浏览器的资源可能会在不同的服务器中,同一个浏览器的网站在不同的服务器中的cookie是不一样的,所以当你请求哪个服务器的资源,携带的就是保存在那个服务器里的专属cookie。)
  • 服务器的access-control-allow-origin不可以写通配符星号,必须写与前台请求头里origins的值完全相同的url。

服务端设置,读取前台的cookie,并返回该数据



前台设置:(只要知道该意思是发送请求时会带上cookie就行)


跨域_第22张图片

跨域_第23张图片
当带了cookie的时候,必须要和当前的域完全匹配,不可以使用通配符星号。
跨域_第24张图片
跨域_第25张图片

以上只适用于一个url访问,如果有多个url访问该怎么解决?因为预请求时请求字段里origins里携带了前台url,所以可以通过后台动态获取origin字段里的数据,写入到access-control-allow-origin里。


跨域_第26张图片
2.调用方解决跨域---隐藏跨域(无法修改被调用方代码的时候)

①nginx代理
②apache代理


跨域_第27张图片
跨域_第28张图片

注意这里写的是相对路径,在浏览器看来是同域的所以不会有跨域问题。 实际上代理服务器会将其请求进行更改。

你可能感兴趣的:(跨域)