一、什么是跨域?
跨域(Cross-origin)是指在浏览器端,一个页面从一个域名跳转到另一个域名的过程。在这个过程中,如果跳转的页面访问了另一个域名下的资源,比如Ajax访问API、通过iframe加载资源等,就会涉及到跨域问题。跨域问题是一个很普遍的网络安全问题,浏览器提供了一些机制限制页面的跨域访问,包括限制Cookie、dom访问、数据读取等。
二、为什么需要跨域配置?
在开发中,通常会存在多个应用系统,有时候需要在这些系统之间进行数据的共享和交换,这时候就会出现跨域问题。跨域的目的是为了限制JavaScript对不同源(domain)的访问,进而保障了网络安全。但是在某些场景下,如果跨域没有设置,将会无法正常调用API或者无法获取到相关资源,导致应用程序无法正常工作。
三、在Spring Boot中配置跨域
Spring Boot通过WebMvcConfigurer类提供了一个非常方便的方式来解决跨域问题。要开启跨域支持,首先需要创建一个WebMvcConfigurer类,并实现addCorsMappings方法。该方法将会配置跨域请求处理的细节,包括允许哪些域名、方法、响应头等。
@Configuration public class CorsConfiguration implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") .maxAge(3600) .allowedHeaders("*") .allowCredentials(true); } }
代码解释:
- addMapping:允许跨域访问的路径
- allowedOrigins:允许跨域访问的域名,设置成“*”表示允许所有来源
- allowedMethods:允许跨域访问的请求方法
- maxAge:缓存时间,在该时间内只需再次发起预检请求
- allowedHeaders:允许跨域访问的请求头
- allowCredentials:是否允许发送Cookie,默认为false
四、Spring Boot跨域配置中的注意点
在进行跨域配置的时候,需要注意以下几点:
1. 支持OPTIONS请求
在进行跨域请求时,会先发一个OPTIONS请求,通过该请求获取服务器的响应,然后才会发送真正的请求。因此必须在跨域配置中加入OPTIONS请求。
@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); }
2. 支持带Cookie的请求
默认情况下,跨域是不支持带Cookie的请求的,可以通过以下配置开启Cookie支持。
@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); }
需要注意的是,允许带Cookie时会增加安全风险,只应在必要时开启。
3. 配置粒度优化
如果想对某个具体的Controller进行跨域配置,可以直接在该Controller中配置。例如下面的代码只对UserController进行跨域配置,而不是全局配置:
@RestController @RequestMapping("/users") public class UserController { @CrossOrigin(origins = "*", maxAge = 3600) @GetMapping public ListgetAllUsers() { return userService.getAllUsers(); } }
需要注意的是,使用@CrossOrigin注解需要搭配配置类中的.addMapping("/users")或全部路径.addMapping("/**"),否则@CrossOrigin注解将不会生效。
五、使用Spring Security配置跨域
在使用Spring Security时,可能会因为跨域而无法进行正常访问,需要进行相应的配置,与跨域配置一样,同样需要重写WebSecurityConfigurerAdapter中的configure方法。
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/**").permitAll() .anyRequest().authenticated() .and().cors().configurationSource(corsConfigurationSource()) } @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.addAllowedOrigin("*"); configuration.addAllowedHeader("*"); configuration.addAllowedMethod("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/api/**", configuration); return source; } }
代码解释:
- anyRequest().authenticated():要求所有请求都要经过认证
- cors():开启跨域
- configurationSource():属性配置
六、总结
在跨域请求的过程中,可以通过配置WebMvcConfigurer或Spring Security来解决跨域问题。正确地配置跨域可以使得应用程序顺畅地工作,增强了跨系统之间的数据共享与交换。