文章目录
前言
一、CROS是什么?
- cross-origin resource sharing,跨域资源共享。一般是在当前页面通过ajax访问了别的应用的页面或者前后端分离应用。
- cros是一种安全机制,且是在浏览器中实现的。通过request的header控制。
二、如何实现
还沿用当初自己对这块的几个疑问,回答疑问的过程,也是梳理的过程。
1.前后端分离应用产生cros问题的原因?
&:前后端分离的应用,前端、后端是2个独立的应用,运行在不同端口。在浏览器看来,是不同的域。前端页面中的ajax请求后端接口,即是跨域访问了,触发cros。
如下截图:浏览器中跨域访问的提示。
因为跨域、且不再允许的来访域,第2次的真实的请求直接没有发送。
2.前后端分离应用如何解决cros问题?
&:有多种方法,其中1个是在后端应用设置允许放入的来访域请求。
对应的后端也支持了preflight(option)请求。
springboot有现成方法。eg:
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* @author: Eli Shaw
* @Date: 2019-05-29 11:18:43
* @Description: CORS 配置允许前端跨域访问
*/
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1
corsConfiguration.addAllowedHeader("*"); // 2
corsConfiguration.addAllowedMethod("*"); // 3
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); // 4
return new CorsFilter(source);
}
}
3.浏览器是如何控制cros的?
&:浏览器对跨域请求,发出preflight;得到后端响应,看响应header中允许的来访域是否包含本域。Access-Control-Allow-Origin: *。
注意观察:预检的方式是option。这也解释了为什么开发调试时,点1次按钮,总是有2个请求发出。实际第1个是preflight,通过会第2个才是真实的请求。
如下图:
- 先预检,只发送request header,并得到response header,得知允许的来访域是*。
- 然后就发送真实的post请求了。
浏览器每次都preflight吗?不影响效率?怎么验证?
4.预检preflight是怎么触发的?怎么做的?
&:preflight是浏览器自动控制的,不需要用户或程序员控制,对用户无感。
当浏览预判可能危害服务器安全时,且满足对应条件,则发出preflight。
也所以说是浏览器中的控制。
总结
CROS流程图
至此,CROS总结:
- 是一种安全机制,限制了跨域访问,一定程度提高安全性;
- 是浏览器控制的,同时受后端允许来访域的影响;对用户无感。
- 基于http协议,预检option类型,然后真实的post。