注:首先我们要明白请求是什么?请求分两种,一、静态请求(如:返回js、css、图片等) 二、动态请求(返回跟用户有关的数据)
http(apache、nginx等)服务器会判断如果是一个静态请求,会直接返回给客户端,如果是一个动态请求http服务器会把这个请求转发到后台的(tomcat等)应用服务器应用服务器处理完后,把结果返回给http服务器,http服务器再返回给客户端
1.为什么会发生AJAX跨域?
①浏览器限制(浏览器处于安全考虑,不允许跨域的xhr请求)
②跨域(协议、域名、端口)
③XHR(XMLHttpRequest)请求
2.解决思路
浏览器=》(XHR=》JSONP)=》(跨域=》(①被调用方 ②调用方))
3.浏览器禁止检查
4.JSONP如何解决跨域
(注:① 普通的ajax请求,请求类型是xhr,jsonp是script ② 普通的ajax请求,返回类型是json,jsonp是javascript)
JSONP其实是前后端共同约定,当请求参数中有callback(因为JSONP只支持GET,参数暴露在url中,callback值在前端自动生成),后端就认定为是jsonp请求,此时后端返回 javascript代码(一个函数),js代码的内容就是一个callback的值为函数名,返回数据做参数的函数。那么这种这种方式为什么能成功呢?它是利用script标签可跨域访问的特性,在发送JSONP时动态创建一个script标签,通过该标签的url属性来发送请求,该url的值就是请求地址加上参数(其中参数自动生成添加了一个callback),把创建出的script元素添加进header头,请求结束后注销这个元素
5.JSONP有什么弊端
①服务器需要改动代码来做支持
②只支持GET
③发送的不是XHR请求(不能使用XMLHttpRequest的新特性)
6.后台解决方案(支持跨域)
①filter解决方案,增加响应头,告诉浏览器支持跨域
跨域请求的请求头里比普通请求多了一个origin,值为当前发送方的域名,当请求返回时浏览器检查返回头里面有没有允许跨域的信息
"Access-Control-Allow-Origin":"请求来源url"
"Access-Control-Allow-Methods":"请求方式"
②简单请求和非简单请求
浏览器在发送请求的时候,会先判断是简单请求还是非简单请求,如果是简单请求会先执行再判断,如果是非简单请求,浏览器会发一个预检命令,检查通过 后才会真正把请求发出去
工作中常见的简单请求:
方法为:GET、HEAD、POST
请求header里面:① 无自定义头 ② Content-Type值为:text/plain、multipart/from-data、application/x-www-form-urlencoded
工作中常见的非简单请求:
①put、delete方法的ajax请求
②发送json格式的ajax请求
③带自定义头的ajax请求
非简单请求时,预检命令请求头中会加上一个Access-Control-Request-Headers:content-type,意为这个请求需要询问服务器后台是否允许这个头,只 有response中加上Access-Control-Request-Headers:content-type这个头,这个预检命令请求才能成功,成功后才真正把请求发出去(所以看到一个请求发 了两次)。(注:非简单请求的method为options)
预检命令缓存,Access-Control-Max-Age:3600,增加这个头等于告诉浏览器一个小时之内缓存这个预检命令请求,意味着一个请求不用发两次了
③带cookie的跨域
此时cookie要加在被调用方,也就是后台,因为在网络请求中只能拿到本域的cookie
此时Access-Control-Allow-Origin的值应为调用方(前台页面)的域名
此时response中要添加上Access-Control-Allow-Credentials:true这样一个字段
④带自定义头的跨域
此时需要在response中的Access-Control-Request-Headers字段值中添加上各自定义请求头字段的key
⑤ nginx、apacha配置等(待叙)
7.调用方解决方案(支持跨域)
隐藏跨域,实现方向代理,nginx、apacha配置等(待叙)