SpringMVC 应用开发
1 基础概念介绍
2 返回值处理
3 参数绑定处理
4 RequestMapping注解
5 RESTful支持
6 拦截器应用
7 CORS跨域解决方案
8 Mock测试(模拟测试)
9 ControllerAdvice
10 乱码解决
11 非注解开发方式
CORS跨域解决方案
- SpringMVC 应用开发
- 一、 什么是跨域
- 二、 如何解决跨域
- 三、 使用CORS跨域
- 3.1 什么是CORS
- 3.2 客户端跨域处理 (了解)
- 3.2.1 对于简单请求
- 3.2.2 非简单请求
- 请求信息
- 3.3 服务器端跨域处理
- 3.3.1 springmvc4.x 以下,使用 springmvc 的拦截器实现
- 跨域不提交Cookie
- 跨域提交Cookie
- 3.3.2 SpringMVC4.x 以上处理 CORS 跨域方式
一、 什么是跨域
浏览器因为安全考虑,所以设置了同源策略。同源策略简单理解就是DNS域名,端口号,协议完全相同
就称为同源。同源下的页面之间才能进行js的dom操作,如果不在同一个源下任何跨文档dom访问都是
被阻止的。不同源下的访问可以称之为跨域访问。
1、端口号不同 http://www.baidu.com/a.js vs. http://www.baidu.com:8080/b.js
2、主域相同子域不同 http://www.baidu.com/a.js vs. http://blog.baidu.com/b.js
3、协议不同 http://www.baidu.com/a.js vs. https://www.baidu.com/b.js
4、域名不同 http://www.baidu.com/a.js vs. http://www.qq.com/b.js
5、域名和对应ip http://www.baidu.com/a.js vs. http://192.168.2.2/b.js
当然在实际应用中,多数出现在ajax请求时,在不同域下请求数据会遇到禁止跨域的问题。
二、 如何解决跨域
1、解决跨域主要考虑两方面:
- 一个是避开 Ajax 请求方式;
- 一个是解决同源限制的问题。
2、解决跨域的方式有多种:
- 基于 JavaScript标签 的 src 方式
- 基于 Jquery 的 JSONP 方式
- 基于 CORS 的方式(解决同源的问题)
JSONP 和 CORS 的区别:
JSONP 只能解决 GET 方式提交
CORS 不仅支持 GET 方式,同时也支持 POST 提交方式。
三、 使用CORS跨域
3.1 什么是CORS
CORS 是一个 W3C 标准,全称是"跨域资源共享"( Cross-origin resource sharing )。
它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限
制。
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能, IE 浏览器不能低于
IE10 。
- CORS 原理:
1、客户端自动向请求头 header 中注入 Origin 。
2、服务器端需要向响应头 header 中注入 Access-Control-Allow-Origin
3、浏览器检测到 header 中的 Access-Control-Allow-Origin ,则就可以跨域操作了。
3.2 客户端跨域处理 (了解)
请求分类标准
浏览器将 CORS 请求分成两类:简单请求( simple request )和非简单请求( not-so-simple request )。
1、 请求方法是以下三种方法之一:HEAD GET POST
2、HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
3.2.1 对于简单请求
浏览器直接发出 CORS 请求。具体来说,就是在头信息之中,增加一个 Origin 字段。
(1)Access-Control-Allow-Origin 该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
(2)Access-Control-Allow-Credentials 该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。 默认情况下,Cookie不包括在CORS请求之中。如果 设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。 这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
3.2.2 非简单请求
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是 PUT 或 DELETE ,或者 Content-Type
字段的类型是 application/json 。
非简单请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为"预检"请求
( preflight )。
请求信息
1、 HTTP 请求的方法是 PUT ,并且发送一个自定义头信息 X-Custom-Header 。
浏览器发现,这是一个非简单请求,就自动发出一个"预检"请求,要求服务器确认可以这样请求。下面
是这个"预检"请求的 HTTP 头信息。
2、"预检"请求用的请求方法是 OPTIONS ,表示这个请求是用来询问的。头信息里面,关键字段是
Origin ,表示请求来自哪个源。
除了 Origin 字段,"预检"请求的头信息包括两个特殊字段。
(1)Access-Control-Request-Method 该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。
(2)Access-Control-Request-Headers 该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom- Header。
3、一旦服务器通过了"预检"请求,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样,会有一个Origin 头信息字段。服务器的回应,也都会有一个 Access-Control-Allow-Origin 头信息字段。
3.3 服务器端跨域处理
3.3.1 springmvc4.x 以下,使用 springmvc 的拦截器实现
cookie 一般也需要跨域提交cookie。
跨域不提交Cookie
java">public class AllowOriginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
// 有跨域行为时参考网址 http://namezhou.iteye.com/blog/2384434
if (request.getHeader("Origin") != null) {
response.setContentType("text/html;charset=UTF-8");
// 允许哪一个URL
response.setHeader("Access-Control-Allow-Origin", "*");
// 允许那种请求方法
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("XDomainRequestAllowed", "1");
System.out.println("正在跨域");
}
return true;
}
}
跨域提交Cookie
注意事项
- Access-Control-Allow-Credentials 为 true 的时候, Access-Control-Allow-Origin 一定
不能设置为”*”,否则报错。 - 如果有多个拦截器,一定要把处理跨域请求的拦截器放到首位。
java">在这里插入代码片public class AllowOriginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
// 有跨域行为时参考网址 http://namezhou.iteye.com/blog/2384434
if (request.getHeader("Origin") != null) {
response.setContentType("text/html;charset=UTF-8");
// 允许哪一个URL 访问 request.getHeader("Origin") 根据请求来的url动态允许
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
// 允许那种请求方法
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,HEAD");
response.setHeader("Access-Control-Max-Age", "0");
// 允许请求头里的参数列表
response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M- With,userId,token");
// 允许对方带cookie访问
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("XDomainRequestAllowed", "1");
System.out.println("正在跨域");
}
return true;
}
}
前端代码:
JS代码
javascript">$.ajax({
url: '自己要请求的url',
method:'请求方式', //GET POST PUT DELETE
xhrFields:{
withCredentials:true
},
success:function(data){
//自定义请求成功做什么
},
error:function(){
//自定义请求失败做什么
}
})
3.3.2 SpringMVC4.x 以上处理 CORS 跨域方式
- 某个方法可以跨域访问,在某个方法上使用 @CrossOrigin
- 某个 Controller 类都可以跨域访问,在类上上使用 @CrossOrigin
- 全局访问,在 springmvc.xml 中配置
<mvc:cors>
<mvc:mapping path="/**"/>
</mvc:cors>