最近自己做的小项目采用前后端完全分离去做,结果出现 invalid cors request 的跨域问题。之前只是简单了解过跨域,解决方式大部分是采用jsonp的形式。
什么叫做跨域
浏览器为了防止CSRF攻击,避免恶意攻击而带来的风险而采取的同源策略限制。浏览器对于javascript的同源策略的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(因为a.cn和b.cn是不同域),所以跨域就出现了。
有一点必须要注意:跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。
跨域的解决方案
跨域是浏览器对同源策略的保护,主流的方式的确是需要前后端配合解决,但是业务需求有千百种,解决方法也应适应业务需求。如果后端服务本身是调取的第三方服务,这种情况下只能纯前端解决了。
①:如果是整个项目都需要跨越,可以采用配置nginx的形式
②采用jsonp,jsonp只可以是get方式
③采用cors的方式,post和get都支持
jsonp跨域的原理
浏览器只对XHR(XMLHttpRequest)请求有同源请求限制,而对script标签src属性、link标签ref属性和img标签src属性没有这这种限制,利用这个“漏洞”就可以很好的解决跨域请求。JSONP就是利用了script标签无同源限制的特点来实现的,当向第三方站点请求时,我们可以将此请求放在标签的src属性里,这就如同我们请求一个普通的JS脚本,可以自由的向不同的站点请求。
spring boot项目中的跨越解决采用cors方式
@Configuration @AutoConfigureBefore(WebSecurityConfig.class) public class CrosConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } }
WebSecurityConfig 增加 cors相关处理
@Override protected void configure( HttpSecurity httpSecurity ) throws Exception { httpSecurity.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() .antMatchers(HttpMethod.POST, "/login","/register").permitAll() .antMatchers(HttpMethod.POST).authenticated() .antMatchers(HttpMethod.PUT).authenticated() .antMatchers(HttpMethod.DELETE).authenticated() .antMatchers(HttpMethod.GET).permitAll() .and() .cors(); }