Tomcat中ajax跨域的问题(CORS)的处理

1.问题现象

当前端使用ajax请求时出现“No 'Access-Control-Allow-Origin' header is present on the requested resource”或者错误信息中包含“CORS ”相关关键字时,就表示你遇到了跨域问题,跨域问题在前端Js中是无法处理的,只有通过后端编码才能解决。

2.概念解释

2.1什么是跨域

当两个域具有相同的协议(如http), 相同的端口(如80),相同的host,那么我们就可以认为它们是相同的域(协议,域名,端口都必须相同)。
跨域就指着协议,域名,端口不一致,出于安全考虑,跨域的资源之间是无法交互的(例如一般情况跨域的JavaScript无法交互,当然有很多解决跨域的方案)

2.2跨域问题的解决方案

为了解决跨域之间的资源共享问题,W3C提出了CORS标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

2.3简单请求和非简单请求

浏览器将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.问题处理

3.1简单请求的处理

在使用jQuery时,发出的GET或POST文本请求默认的Content-Type为text/plain或multipart/form-data,此时归类为简单请求,对于简单请求,服务端只需要设置response的Access-Control-Allow-origin即可,可以设置为request头中的origin值,也可以设置为*

String origin = request.getHeader("Origin");
if("http://www.mysite.com".equals(origin)){
  response.addHeader("Access-Control-Allow-Origin", origin);
  response.addHeader("Access-Control-Allow-Credentials", "true");
}

3.2非简单请求的处理

使用axios时,默认请求头中的Content-Type为application/json,此时为非简单请求,在服务端除了设置Access-Control-Allow-origin外,还需要设置Access-Control-Allow-Methods和Access-Control-Request-Headers

String origin = request.getHeader("Origin");
if("http://www.mysite.com".equals(origin)){
  response.addHeader("Access-Control-Allow-Origin", origin);
  response.addHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
  response.addHeader("Access-Control-Allow-Credentials", "true");
  response.addHeader("Access-Control-Max-Age", String.valueOf(24*60*60));
  String header = request.getHeader("Access-Control-Request-Headers");
  if(header!=null) {
    response.addHeader("Access-Control-Allow-Headers", header);
  }
}

4.Request和Response头的解释

浏览器在发出非简单请求的跨域请求时,会先发送预检请求,此请求的方法为OPTIONS,此时会在Request的请求头上带上Access-Control-Request-Method和Access-Control-Request-Method,服务器可以根据request请求头的内容返回Access-Control-Allow-origin、Access-Control-Allow-Methods、Access-Control-Request-Headers、Access-Control-Max-Age、Access-Control-Allow-Credentials等信息,浏览器根据返回的response头中的信息与即将发出的请求进行对比,符合规则的才发出请求,不符合规则的直接提示CORS错误

4.1Request请求头

4.1.1Access-Control-Request-Method

该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,一般是POST,当调用其他类型的请求时,会按请求的方法名来显示

4.1.2Access-Control-Request-Headers

该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,一般为Content-Type,当指定了特殊请求头时,会显示特殊请求头的名称

4.2Response请求头

4.2.1Access-Control-Allow-Origin

该字段必需,他的值要么是请求Origin字段的值,要么是一个*, 表示接受任意域名的请求

4.2.2Access-Control-Allow-Methods

该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

4.2.3Access-Control-Allow-Headers

如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

4.2.4Access-Control-Allow-Credentials

有这个头或者值为true,表示可接受跨域的cookies。而withCredentials是客户端设置是否传递cookies到服务器。

4.2.5Access-Control-Max-Age

该字段可选,用来指定本次预检请求的有效期,单位为秒。上面例子代码中,有效期是1天(24*60*60秒),即允许缓存该条回应1天,在此期间,不用发出另一条预检请求。

5.参考

跨域(CORS)产生原因分析与解决方案,这一次彻底搞懂它 - 知乎Cross-origin Resource Sharing 中文名称 “ 跨域资源共享” 简称 “CORS”,它突破了一个请求在浏览器发出只能在同源的情况下向服务器获取数据的限制。本文会先从一个示例开始,分析是浏览器还是服务器的限制,之…https://zhuanlan.zhihu.com/p/210244307
跨域资源共享 CORS 详解CORS是一个W3C标准,全称是\x26quot;跨域资源共享\x26quot;(Cross-origin resource sharing)。\x0a它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。https://mp.weixin.qq.com/s?src=3×tamp=1642468718&ver=1&signature=UjH5AXilQDbckV1N3Kjh9RCGhWCbGALOc4NP2W56*ArHT9dKPMxAQ3vPGM4Ijn-8PE9gxc6onTjZEgiMNYUdZL5NqCkdkhQ*NiM-6ynl4DMsd-R-Id8jU5Ue2FNMCrgoYaMZ9ybzNHDcE7WSoTlG1xihJd*eG*6pYz1wP2vbChA=跨域共享CORS详解及Gin配置跨域 - 常见-youmen - 博客园跨域简介 当两个域具有相同的协议(如http), 相同的端口(如80),相同的host,那么我们就可以认为它们是相同的域(协议,域名,端口都必须相同)。 跨域就指着协议,域名,端口不一致,出于安全考虑https://www.cnblogs.com/you-men/p/14054348.html

猜你喜欢

转载自blog.csdn.net/shuaijie506/article/details/122552991