一、出现跨域的原因
浏览器基于安全性考虑,为了防止非同源的请求拿到服务器的返回数据结果。实际上请求已经发送出去了,但服务端正常返回结果后被浏览器拦截了。
二、什么是跨域请求
请求来源与请求目标的协议(如http和https)、域名、端口号不同的请求,都是跨域请求。
例如以下请求,都是跨域请求
从http://example.com 请求 https://example.com
从http://a.example.com 请求 http://b.example.com
从http://example.com:80 请求http://example.com:81
三、跨域请求方法,以及Nginx的不同处理方式
一般来说,我们常用的HTTP请求是HEAD、GET,非常用的是PUT、DELETE、POST
1、对于常规请求方式(HEAD、GET),直接在nginx上增加以下配置即可;
add_header Access-Control-Allow-Origin '*' always; # 可以指定来源,如:example.com
add_header Access-Control-Allow-Headers 'Keep-Alive,logintype,User-Agent,Cache-Control,Content-Type,Authorization,Auth-Token' always;
add_header Access-Control-Max-Age 1728000;
add_header Access-Control-Allow-Methods 'GET,POST,OPTIONS,PUT' always;
2、对于非常规请求方式(PUT、DELETE、POST),一般都带有验证头部信息,如token,仅增加如上配置,还是会遇到跨域报错。因为对于非常规请求,浏览器会分成2步处理:
a、预检(preflight)请求:在真正请求前进行一次预检(preflight)请求,请求方法是OPTIONS,浏览器进行校验,如果返回状态码是2XX(通常是204)表示验证通过
b、正式请求:在预检请求通过后,浏览器向服务器发送正式请求
针对这种情况,解决办法是在nginx上增加如下配置
add_header Access-Control-Allow-Origin '*' always; # 可以指定来源,如:example.com
add_header Access-Control-Allow-Headers 'Keep-Alive,logintype,User-Agent,Cache-Control,Content-Type,Authorization,Auth-Token' always;
add_header Access-Control-Max-Age 1728000;
add_header Access-Control-Allow-Methods 'GET,POST,OPTIONS,PUT' always;
add_header Access-Control-Allow-Credentials true; #是否携带cookie
if ($request_method = 'OPTIONS') {
return 204;
}