跨域是什么:
域名和端口不同的服务之间针对ajax访问限制即跨域问题;
解决办法
- Jsonp
利用script标签可以跨域原理实现,只支持get请求;
- nginx反向代理
利用反向代理把跨域为不跨域,支持各种请求方式!
- CORS
支持各种请求方式,在服务端进行控制,可自定义规则;但是会产生额外的请求;
CORE
跨域资源共享标准( cross-origin sharing standard )允许在下列场景中使用跨域 HTTP 请求:
因为出于安全的考虑, 浏览器不允许Ajax调用当前源之外的资源. 即浏览器的同源策略.
CORS需要浏览器和服务器同时支持。目前,所有主流浏览器都支持该功能,IE浏览器不能低于IE10。在浏览器端, 整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,用户对这些都不会有感觉。因此,实现CORS通信的关键是服务器。
浏览器将跨域请求分为两大类: 简单请求和非简单请求.
简单请求
- a. 请求方式为下列之一:
- GET
- POST
- HEAD
- b. 请求头信息不超出以下字段:
- Accept
- Accept-Language
- Content-Language
- Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是同时满足以上两个条件的, 就是简单请求.
对于简单请求, 浏览器直接发出CORS请求, 即浏览器自动在请求header中加上Origin
字段, 告诉服务器这个请求来自哪个源(请求协议+域名+端口). 服务器收到请求后, 会对比这个字段, 如果字段值不在服务器的许可范围内, 服务器会返回一个正常的HTTP响应, 但是其响应头中不会包含Access-Control-Allow-Origin
字段, 浏览器发现后, 就会抛出一个异常提示响应头中没有这个字段. 如果这个源在服务器的许可范围内, 服务器的响应头会加上以下字段:
Access-Control-Allow-Origin:http://ip:port
必需项, 值为请求头中的Origin
的值.Access-Control-Allow-Credentials:true
可选项, 值为boolean, 表示是否允许浏览器发送cookie, 需要在服务器配置.Access-Control-Expose-Headers:
浏览器可以从跨域请求响应头中获取的字段值, 由服务器配置. 默认可以获取Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma
这六个字段.
如果服务器允许跨域
Access-Control-Allow-Origin: http://manage.leyou.com
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8
非简单请求
对于非简单请求, 浏览器的CORS
请求分为两步, 首先是执行预检(preflight)
请求, 询问服务器是否允许当前源访问, 如果允许, 才会执行实际请求, 预检请求可以缓存(缓存时间由服务器定义), 在缓存有效期内再执行CORS请求时无需进行预检请求.
预检请求
- a. 预检请求的请求方式为
OPTIONs
, 表示这个请求是用来询问的。 - b. 请求头信息包含以下字段:
- Origin: 请求源.
- Access-Control-Request-Method: cors请求会用到的请求方式.
- Access-Control-Request-Headers: cors请求会额外发送的请求头字段.
- c. 服务器收到预检请求后会检查上面的三个字段值以确定是否允许跨域请求, 如果任意一项不完全满足则都不允许进行跨域请求.
- d. 预检请求的响应中会包含如下字段:
- Access-Control-Allow-Origin:
必需项, 值为请求头中的Origin
的值. - Access-Control-Allow-Credentials:
可选项, 值为boolean, 表示是否允许浏览器发送cookie, 需要在服务器配置. - Access-Control-Allow-Headers:
可选项, 允许跨域请求额外发送的header字段, 需要在服务器配置. - Access-Control-Allow-Methods:
必需项, 允许跨域请求的请求方式. - Access-Control-Max-Age:
必需项, 预检请求的缓存时间.
- Access-Control-Allow-Origin:
如果预检请求正常返回, 接下来执行实际请求. 在预检请求缓存有效期内, 再执行跨域请求时无需进行预检请求.
===========================================================================================
Spring跨域请求配置
@CrossOrigin这个注解可以用于类上和方法上. 其属性有:
- origins:
允许跨域请求的源, 如果是*
, 则表示允许所有的源进行跨域请求. 默认为所有. - allowedHeaders:
允许跨域请求传入的header字段, 默认为所有. - exposedHeaders:
浏览器可以从跨域请求响应头中获取的字段值. - methods:
允许跨域请求的请求方式, 默认为所有. - allowedCredentials:
允许跨域请求上传cookie或用户凭证等信息, 默认为false, 不启用. - maxAge:
浏览器缓存预检请求的时间.
配置服务器服务允许跨域
@Configuration public class GlobalCorsConfig { @Bean public CorsFilter corsFilter() { //1.添加CORS配置信息 CorsConfiguration config = new CorsConfiguration(); //1) 允许的域,不要写*,否则cookie就无法使用了 config.addAllowedOrigin("http://manage.leyou.com"); config.addAllowedOrigin("http://www.leyou.com"); //2) 是否发送Cookie信息 config.setAllowCredentials(true); //3) 允许的请求方式 config.addAllowedMethod("OPTIONS"); config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); // 4)允许的头信息 config.addAllowedHeader("*"); // 5)有效时长 config.setMaxAge(3600L); //2.添加映射路径,我们拦截一切请求 UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); //3.返回新的CorsFilter. return new CorsFilter(configSource); } }