当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
当前页面url | 被请求页面url | 是否跨域 | 原因 |
---|---|---|---|
http://www.test.com/ | http://www.test.com/index.html | 否 | 同源(协议、域名、端口号相同) |
http://www.test.com/ | https://www.test.com/index.html | 跨域 | 协议不同(http/https) |
http://www.test.com/ | http://www.baidu.com/ | 跨域 | 主域名不同(test/baidu) |
http://www.test.com/ | http://blog.test.com/ | 跨域 | 子域名不同(www/blog) |
http://www.test.com:8080/ | http://www.test.com:7001/ | 跨域 | 端口号不同(8080/7001) |
解决方案
前后端结合(JsonP)
虽然jsonp也可以实现跨域,但是因为jsonp不支持post请求,应用场景受限
纯后端方式
CORS
cors是w3c标准的方式,通过在web服务器端涉及:响应头Access-Cntrol-Alow-Origin来指定哪些域可以访问本域的数据
在Controller上加@CrossOrigin注解或者做全局配置
服务器代理,同源策略只存在浏览器端,通过服务器转发请求可以达到跨域请求的目的
劣势:增加服务器的负担,并且访问速度慢
Nginx
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET,POST,OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
add_header Access-Control-Max-Age 3600;
return 204;
}
proxy_pass http://127.0.0.1:8081;
}
预检请求(preflight request)
跨域资源共享(CORS)标准新增了一组HTTP首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对哪些可能对服务器数据产生副作用的HTTP请求方法(特别是GET意外的HTTP请求,或者搭配某些MIME类型的POST请求),浏览器必须首先使用OPTIONS方法发起预检请求,从而获知服务端是否允许该跨域请求。服务器确认允许后,才发起时间的HTTP请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括Cookies和HTTP认证相关数据)。
其实Content-Type字段的类型为application/json的请求就是上面说的搭配某些MIME类型的POST请求。