一,什么是跨域:
1,请求协议 http ,https 的不同
2,域的 domain 的不同
3,端口 port 的不同
二,简单请求,复杂请求
1,请求方式只能是:head get post
2,请求头允许的字段: Accept,Accept-Language,Content-Language,Last-Event-ID
content_type : application/x-www-form-urlencoded、multipart/form-data、text/plain 三选一
复杂请求:除以上方式,比如:options
三,谷歌浏览器,在非跨域情况下,也会发送 origin 字段
origin 相当于一个验证,看是否符合要求
其中最重要的就是 Access-control-allow-origin, 标识允许哪个域的请求。当然,如果服务器不通过,根本没有这个字段,接着触发 XHR 的 onerror,再接着你就看到浏览器的提示 xxx的服务器没有响应 Access-control-allow-origin 字段
//指定允许其他域名访问
'Access-Control-Allow-Origin:http://172.20.0.206'//一般用法(*,指定域,动态设置),3是因为*不允许携带认证头和cookies
//是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回
'Access-Control-Allow-Credentials:true'
上面第一行说到的Access-Control-Allow-Origin有多种设置方法:
1,设置 * 是最简单粗暴的,但是服务器出于安全考虑,肯定不会这么干,而且,是 * 的话,浏览器将不会发送 cookies,即使你的 XHR 设置了 withCredentials
, 2,指定域,如上图中的http://172.20.0.206,一般的系统中间都有一个nginx,所以推荐这种
3,动态设置为请求域,多人协作时,多个前端对接一个后台,这样很方便 ,
withCredentials:表示XHR是否接收cookies和发送cookies,也就是说如果该值是false,响应头的Set-Cookie,浏览器也不会理,并且即使有 目标站点的cookies,浏览器也不会发送。
复杂请求:
最常见的情况,当我们使用put和delete请求时,浏览器会先发送option(预检)请求,不过有时候,你会发现并没有
预检请求:
与简单请求不同的是,option请求多了2个字段:
Access-Control-Request-Method:该次请求的请求方式
Access-Control-Request-Headers:该次请求的自定义请求头字段
服务器检查通过后,做出响应:
//指定允许其他域名访问
'Access-Control-Allow-Origin:http://172.20.0.206'
//一般用法(*,指定域,动态设置),3是因为*不允许携带认证头和cookies//是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回
'Access-Control-Allow-Credentials:true'
//预检结果缓存时间,也就是上面说到的缓存啦
'Access-Control-Max-Age: 1800'
//允许的请求类型
'Access-Control-Allow-Methods:GET,POST,PUT,POST'
//允许的请求头字段
'Access-Control-Allow-Headers:x-requested-with,content-type'
ajax请求跨域,需要在方法体中,加入请求头部信息:
public String bszSelectUser() throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
Map session = ActionContext.getContext().getSession();
HttpServletResponse response = ServletActionContext.getResponse();
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST, GET,OPTIONS,DELETE,PUT");
response.addHeader("Access-Control-Allow-Headers", "Test");
/*....代码部分...*/
}