跨域学习笔记
笔记内容来自慕课网的视频教程
链接: 慕课网教程地址.
跨域产生的原因
跨域产生的原因并不是因为服务器后台不允许前台调用,而是浏览器出于安全的考虑对跨域的请求进行校验,校验不通过时,浏览器就会报错。
什么情况下会跨域呢:
1.浏览器限制
2.协议、域名、端口,任何一个不相同都会跨域(前台地址和请求的后台地址对比)
3.XHR(XMLHTTPRequest)请求
满足以上3点才会请求失败
解决思路
- 第一种呢就是直接去除浏览器的校验,这种方式需要每个客户端都要修改,并不实际;
- 第二种方法:改变请求的类型,只要发送的请求不是XHR请求,浏览器就不会进行校验,也就不会报跨域的错误,解决方案是jsonp;
- 第三种方式就是解决跨域,由于jsonp的解决方式有很多弊端,无法满足现在的开发需要;解决跨域的思路有两种:被调用方支持跨域、调用方隐藏跨域。
解决方式
功能快捷键
1.屏蔽浏览器校验,启动浏览器时,配置指定的参数,禁止浏览器进行校验,然后通过这个启动的浏览器进行任何访问都不会出现跨域错误
2.使用jsosp进行请求
使用jsonp请求后台需要改动吗?
答案是需要,后台需要返回的是一个js脚本而不是一个json对象
写一个切面来为转化请求的返回方式,直接继承AbstractJsonpRequestBodyAdvice,约定参数标识
这相当于你在请求中拿到callback的参数,如果有这个参数,代表这个请求是约定好的jsonp请求,但回执就拼接成这样的形式:
callback+"("+JSON.toJSONString(responseData)+");"
是一个js方法的形式
前台的请求
$.ajax({
url: base +"/test",
dataType: "jsonp", //请求方式
jsonp: "callback", //约定标识
cache:true,
success: function(json){
result = json;
}
});
***callback只是一个约定,也可以约定为其他的名字***
接收jsonp请求会发现有一个 _参数,这个是为了防止请求被缓存
如果设置请求中cache:true,这个参数就不会出现了。
缺点:
1.只支持get请求,就算指定请求方式为其他,也不会生效
2.xhr请求有很多新特性,jsonp没有
跨域解决方案
架构图示例:
1.简单请求:
方法:GET HEAD POST
请求header中无自定义头
Content-Type为一下几种:
text/plain
multipart/form-data
application/x-www-form-urlencoded
2.非简单请求,浏览器会发送options预检命令
put,delete方法的ajax请求
发送json格式的ajax请求
带自定义头的ajax请求
3.浏览器如何检测:
跨域请求的请求头中,多了一个参数
Origin:当前域名信息
当请求中有这个参数,浏览器就会在响应中检测有没有跨域的参数信息,如果没有,就会报错
4.浏览器的检测时机:
简单请求:先执行,后判断;
非简单请求:先判断后执行 ;先发送预检命令,通过后,再发送请求。
这个预检请求的头中有两个有关字段
Access-Control-Request-Header:content-type
Access-Control-Request-Method:POST
被调用方filter的解决方案
被调用方解决思路—通知浏览器,允许指定域调用(修改响应头,通知浏览器允许访问)
1.使用filter,在应用中实现允许跨域
别忘了调用filter链
这两个参数可以使用*来匹配所有情况
如果是非简单请求,还需要增加对请求头的允许,来通过浏览器的预检命令,如果是多个,可以用逗号分隔 也可以配置成动态的,见带自定义头的跨域
res.addHeader("Access-Control-Allow-Headers", "Content-Type");
预检命令的缓存,这个参数意思是告诉浏览器预检命令结果可以缓存的时长,单位是秒
带cookie的请求
withCredentials: true这个参数代表发送的请求带有cookie,这里的cookie指的是被调用方的cookie,而不是调用方的cookie
带cookie的时候,需要注意的有两点:
1.要新增一个参数:
Access-Control-Allow-Credentials:true
2.Access-Control-Allow-Origin 的值不能使用* 来通配,必须是全匹配
但是这样就只能匹配一个地址了,所以我们可以这样处理:
取出请求中的地址,放到这个字段的配置中去
带自定义头的跨域
使用jq发送带自定义请求头的请求,两种添加请求头的方法:
这样请求头中会出现一个参数,代表有自定义的请求头
请求头的允许也可以配置成为动态的
在http服务器中配置解决
虚拟主机:多个域名,指向同一个服务器,看上去有多个主机,实际上只有一个
打开nginx的配置文件,nginx.conf
在最后面增加一句话:
来载入这个目录下的所有后缀是.conf的文件
然后在这个文件下创建一个配置文件,来进行接下来的配置
apache解决方案
hpptd.conf文件:
虚拟主机模块
虚拟主机的配置文件
在这个文件中配置一个虚拟主机:
这里使用了proxy模块,需要将模块配置启用
在虚拟主机中加入配置信息:
这里使用了Headers和Rewrite模块,需要将模块配置打开
spring框架中的快捷解决方案
使用@CrossOrigin注解来解决跨域
springMVC的版本要在4.2或以上版本才支持@CrossOrigin
这个注解可以在类上,也可以在方法上
注解不起作用的原因
调用方解决方案
解决思路:
使用http服务器将被调用方的代理为
前台请求时,需要使用代理后的地址(/ajaxserver)来访问
这样前台调用的地址就会转换为本域的地址
apache的配置图示
笔记内容来自慕课网的视频教程
链接: 慕课网教程地址.