跨域请求一直是网页编程中的一个难题,在过去,绝大多数人都倾向于使用JSONP来解决这一问题。不过现在,我们可以考虑一下W3C中一项新的特性——CORS(Cross-Origin Resource Sharing)了。
客户端:
创建XmlHttpRequest对象:
对于CORS,Chrome、FireFox以及Safari,需要使用XmlHttpRequest2对象;而对于IE,则需要使用XDomainRequest。
CORS的前端请求可以分成两种:
- 简单请求
- 复杂请求
一个简单的请求大致如下:
- HTTP方法是下列之一
HEAD
GET
POST
- HTTP头包含
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type
,但仅能是下列之一application/x-www-form-urlencoded
multipart/form-data
text/plain
任何一个不满足上述要求的请求,即被认为是复杂请求。一个复杂请求不仅有包含通信内容的请求,同时也包含预请求(preflight request)。
简单请求:
在回应中,COR相关的项目全都是以“Access-Control-
”作为前缀的,其意义分列如下:
Access-Control-Allow-Origin
(必含)- 不可省略,否则请求按失败处理。该项控制数据的可见范围,如果希望数据对任何人都可见,可以填写“*”。Access-Control-Allow-Credentials
(可选) – 该项标志着请求当中是否包含cookies信息,只有一个可选值:true
(必为小写)。如果不包含cookies,请略去该项,而不是填写false
。这一项与XmlHttpRequest2
对象当中的withCredentials
属性应保持一致,即withCredentials
为true
时该项也为true
;withCredentials
为false
时,省略该项不写。反之则导致请求失败。
spring可以用Filter、注解或配置实现。
复杂请求:
来看看预回应当中可能的项目:
Access-Control-Allow-Origin
(必含) – 和简单请求一样的,必须包含一个域。Access-Control-Allow-Methods
(必含) – 这是对预请求当中Access-Control-Request-Method
的回复,这一回复将是一个以逗号分隔的列表。尽管客户端或许只请求某一方法,但服务端仍然可以返回所有允许的方法,以便客户端将其缓存。Access-Control-Allow-Headers
(当预请求中包含Access-Control-Request-Headers
时必须包含) – 这是对预请求当中Access-Control-Request-Headers
的回复,和上面一样是以逗号分隔的列表,可以返回所有支持的头部。Access-Control-Allow-Credentials
(可选) – 和简单请求当中作用相同。Access-Control-Max-Age
(可选) – 以秒为单位的缓存时间。预请求的的发送并非免费午餐,允许时应当尽可能缓存。
一旦预回应如期而至,所请求的权限也都已满足,则实际请求开始发送。