AJAX跨域拦截解决思路

为什么会发生AJAX跨域?

1.浏览器限制
当浏览器发现请求是跨域的时候,它会做一些校验,如果校验不通过它就会报跨域安全错误。

2.跨域
发出去的请求,协议、端口、请求地址,任何一个不一样,浏览器就会认为是跨域。

3.发送的是 XHR(XMLHttpRequest) 请求
如果发送的不是XHR请求,就算是跨域,浏览器也不会报错。

解决问题的思路
1.浏览器限制,我们就解除浏览器的跨域限制,从命令行中启动chrome。

open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=/Users/wenxiangye/MyChromeDevUserData/

2.JSONP如何解决跨域问题?
利用JQ实现JSONP请求

$.ajax({
url: base+"/get1",
dataType: “jsonp”,
jsonp: “callback2”, //默认不写前后端约定的名称是 callback
cache: true, //表示结果可以被缓存,jsonp请求url中不会带 _字段
success: function(json){
result = json;
}
})
1
2
3
4
5
6
7
8
9

有三个不同点:

  1. 请求的Type不同
  2. 请求返回的 Content-Type 不同
  3. JSON请求的URL后面自动加了callback

动态创建

动态创建的script请求完毕后会被销毁,所以dom结构中无法查看,需要再JQ源码中9816行出打断点查看。

jsonp请求里面除了callback参数之外还多了一个_参数,参数值是一个随机的数字,防止请求被缓存。

JSON弊端:

服务器需要做一些改动。
只支持GET
发送的不是XHR请求,(XHR有很多新的特性,比如异步。)
3.被调用方解决跨域问题
响应头增加字段,告诉浏览器允许跨域。
浏览器发现请求是跨域的时候,他会在请求头增加当前域的字段Origin: http://localhost:8081 等请求返回来,他会检查响应头里面的字段信息,是否允许跨域。
后端需要在响应头增加 :
Access-Control-Allow-Origin:http://localhost:8081
Access-Control-Allow-Methods:GET
两个字段都可以填写*表示所有域名和请求都可以跨域

简单请求和非简单请求
浏览器在发送跨域请求的时候,会先判断跨域是简单请求还是非简单请求,如果是简单请求它会先执行,后判断。如果是非简单请求,会发一个OPTIONS的预检命令,检查通过后,他会把真正的请求发送过去。

简单请求的定义:方法为GET POST HEAD 、无自定义头部、Content-Type为:text/plain、multipart/form-data、application/x-www-form-urlencoded 三种。
非简单请求:方法为 PUT, DELETE 方法的ajax请求、发送json格式的ajax请求、带自定义头的请求
非简单请求时,如果跨域了,浏览器首先发送一个OPTIONS预检请求,在预检请求中会有一个字段 Access-Control-Request-Method: content-type ,询问后台服务器是否允许 content-type 这个头,如果响应头部没有通过的信息,就会报跨域的错误。

解决方法: 后台代码需要增加头信息 Access-Control-Allow-Headers: Content-Type

非简单请求每个跨域请求都会请求两次,这样非常影响效率,响应可以增加一个头信息,来缓存预检命令,Access-Control-Max-Age: 3600 这个头信息的意思是告诉浏览器,在3600秒内,可以缓存预检命令的结果,不需要发送预检命令。

带cookie的跨域:当响应头Access-Control-Allow-Origin: * 时,是不能满足带cookie的跨域请求的,前端设置 :

$.aiax({
…,
xhrFields:{
withCredentials:true
}

})
1
2
3
4
5
6
7
后端设置头信息 Axxess-Control-Allow-Origin: http://localhost:8081和Access-Control-Allow-Credentials: true

但是这样做之后,浏览器只会允许 http://localhost:8081 这个地址来跨域,如果需要多个地址请求实现跨域如何实现呢?
之前知识点: 浏览器发现请求是跨域的时候,他会在请求头增加当前域的字段Origin: http://localhost:8081 等请求返回来,他会检查响应头里面的字段信息,是否允许跨域。
后端可以动态的去取 Origin这个字段的值,如果不为空,则 Axxess-Control-Allow-Origin: Origin,现在就可以支持任何的跨域调用了。

带自定头的跨域
首先前端定义:

可以发现请求头部增加了如下内容:

此时去请求发现报错

报错信息的意思是:在返回头Access-Control-Allow-Headers 字段中没有 x-header2 的信息,把 x-header1 x-header2 加进去就行了,最好是动态的获取请求头Origin里面的值去添加,这样就支持所有的自定义头部了。

虚拟主机上设置响应头信息
之前我们是直接在应用服务器上面修改响应头信息,现在我们建立一个虚拟主机,在虚拟主机上面修改响应头信息
被调用方的虚拟主机的配置。

第一步首先配置HOST文件eg:

127.0.0.1 b.com
1
打开nginx中的config目录 新建一个 vhost目录,在里面新建虚拟主机的配置文件。打开 nginx.config 文件,在最后增加

include vhost/*.conf //让nginx载入这个目录下的所有.conf文件
1
在vhost目录中新建一个 b.com.config文件,里面写入下面代码

server{
listen 80; //监听的端口
server_name b.com; //监听的域名
location /{
proxy_pass http://localhost:8080/; //把所有的请求都转到 8080,监听80端口,域名为b.com
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Max-Age 3600;
add_header Access-Control-Allow-Credentials true;

    add_header Access-Control-Allow-Origin $http_origin;  //获取请求头里面的值
    add_header Access-Control-Allow-Headers $http_access_control_request_headers;
    if ($request_method = OPTIONS){
        return 200;   //把跨域的预检命令直接在虚拟主机上处理,不经过应用主机。
    }
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
启动nginx start nginx

4.调用方解决跨域
通过反向代理来实现,隐藏跨域。

正向代理:它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求,正向代理的过程,它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求。

反向代理:它隐藏了真实的服务端,当我们请求 www.baidu.com 的时候,就像拨打10086一样,背后可能有成千上万台服务器为我们服务,但具体是哪一台,你不知道,也不需要知道,你只需要知道反向代理服务器是谁就好了,www.baidu.com 就是我们的反向代理服务器,反向代理服务器会帮我们把请求转发到真实的服务器那里去。Nginx就是性能非常好的反向代理服务器,用来做负载均衡。

两者的区别在于代理的对象不一样:正向代理代理的对象是客户端,反向代理代理的对象是服务端。
摘自知乎-刘志军的回答

127.0.0.1 b.com a.com //增加一个a.com,用它表示调用方的虚拟主机
1
在vhost目录中新建一个 a.com.config文件,里面写入下面代码

server {
listen 80:
server_name a.com;

location /{
    proxy_pass http://localhost:8081/;
}

location /ajaxserver{ //把我们要调用的服务器代理成 ajaxserver
    proxy_pass http://localhost:8080/test/; 
}

}
1
2
3
4
5
6
7
8
9
10
11
12
请求的代码中修改请求的基本前缀

var base = ‘/ajaxserver’

作者:yewenxiang
来源:CSDN
原文:https://blog.csdn.net/yewenxiang/article/details/80115103
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值