跨域请求ajax,在正式发出请求前会自动发送一个preflight request请求,这个请求方式是options,不带cookie和参数,拿到服务器返回如果Access-Control-Allow-Origi允许当前域名跨域访问,那么随后会正式发送你的ajax请求。如果不允许就会报错。
要注意preflight request请求的地址和正常请求地址是一样的,注意没有cookie和参数,后台业务逻辑要注意NPE问题。
HTTP请求头参考https://www.jianshu.com/p/d05303d34222
#请求域
Origin: ”http://localhost:3000“
#这两个属性只出现在预检请求中,即OPTIONS请求
Access-Control-Request-Method: ”POST“
Access-Control-Request-Headers: ”content-type“
HTTP响应头,参考https://www.jianshu.com/p/d05303d34222
#允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
Access-Control-Allow-Origin: ”http://localhost:3000“
#允许访问的头信息
Access-Control-Expose-Headers: "Set-Cookie"
#预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
Access-Control-Max-Age: ”1800”
#允许Cookie跨域,在做登录校验的时候有用
Access-Control-Allow-Credentials: “true”
#允许提交请求的方法,*表示全部允许
Access-Control-Allow-Methods:GET,POST,PUT,DELETE,PATCH
下面是一个在百度网页中跨域请求另一个网站的network信息:
Request URL:http://bike-api.jdd.com/bike/api/game/status.do
Request Method:OPTIONS
Status Code:200 OK
Remote Address:192.168.137.142:80
Referrer Policy:unsafe-url
Response Headers
view source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:device
Access-Control-Allow-Methods:POST
Access-Control-Allow-Origin:http://www.baidu.com
Access-Control-Max-Age:1800
Allow:GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Connection:keep-alive
Content-Length:0
Date:Tue, 02 Jan 2018 11:25:57 GMT
Server:nginx
Vary:Origin
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6
Access-Control-Request-Headers:device
Access-Control-Request-Method:POST
Connection:keep-alive
Host:bike-api.jdd.com
Origin:http://www.baidu.com
Referer:http://www.baidu.com/
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36
编写CORS可以用CorsFilter,CorsInterceptor和@CorsOrigin(在Controller上加)3种方法。
CorsFilter可以对全部url起作用,interceptor只拦截springmvc请求,@corsorigin只对某个Controller起作用。
任务:pre-flight request会经过interceptor,不知到会不会进入controller执行业务逻辑???
理想情况下,pre-flight request应该在CorsFilter或者CorsInterceptor直接返回,不应该进入用户的filter,interceptor和controller.