Spring Boot 中的 CORS 策略冲突
Posted
技术标签:
【中文标题】Spring Boot 中的 CORS 策略冲突【英文标题】:CORS policy conflict in Spring boot 【发布时间】:2019-11-07 14:46:36 【问题描述】:我是 Spring Boot 新手,我使用 Spring Boot 实现了一些基本的 REST API。当我尝试使用 react 调用这些 api 时,调用某些 CORS 策略时出错。然后我找到了解决该问题的方法,并且我的所有 api 端点都可以正常工作,除了登录 api 调用。我得到同样的错误调用:
这是我的网络安全 java 类。
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter
private final UserService userDetailsService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public WebSecurity(UserService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder)
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
@Override
protected void configure(HttpSecurity http) throws Exception
http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL)
.permitAll().anyRequest().authenticated().and().cors().and().addFilter(getAuthenticationFilter())
.addFilter(new AuthorizationFilter(authenticationManager())).sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
public AuthenticationFilter getAuthenticationFilter() throws Exception
final AuthenticationFilter filter = new AuthenticationFilter(authenticationManager());
filter.setFilterProcessesUrl("/users/login");
return filter;
这是我的示例控制器类。
@RestController
@RequestMapping("/users")
public class UserController
@Autowired
UserService userService;
@CrossOrigin
@GetMapping(path = "/id",
produces = MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE )
public UserRest getUser(@PathVariable String id)
UserRest returnValue = new UserRest();
UserDto userDto = userService.getUserByUserId(id);
BeanUtils.copyProperties(userDto, returnValue);
return returnValue;
@CrossOrigin
@PostMapping(
consumes = MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE ,
produces = MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE )
public UserRest createUser(@RequestBody UserDetailsRequestModel userDetails)
UserRest returnValue = new UserRest();
UserDto userDto = new UserDto();
BeanUtils.copyProperties(userDetails, userDto);
UserDto createUser = userService.createUser(userDto);
BeanUtils.copyProperties(createUser, returnValue);
return returnValue;
我被这个问题困住了,我真的需要一些帮助。我已经尝试过 *** 中给出的一些与我的问题类似的答案。但这并没有解决我的问题。 Mt spring boot 版本是2.1.4
【问题讨论】:
【参考方案1】:试试这个,
@Configuration
public class WebConfiguration implements WebMvcConfigurer
@Override
public void addCorsMappings(CorsRegistry registry)
registry.addMapping("/**")
.allowedMethods("*");
更新
你也可以这样做,
@Bean
public FilterRegistrationBean corsFilter()
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(Collections.singletonList("*"));
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> filterRegistration = new FilterRegistrationBean<>(new CorsFilter(source));
filterRegistration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistration;
【讨论】:
谢谢@Avi。但是我的问题解决了。顺便谢谢 解决方案是什么?【参考方案2】:您正面临这个问题,因为您已经允许后端从端口 8080 进行 cors,但您的反应在本地端口 3000 中启动。因此,springboot 不会接受来自不同端口地址的请求。
方法一:
您可以通过使用以下注释来解决这个问题:
@CrossOrigin(origins = "http://localhost:3000", maxAge = 3600)
由于您使用的是 springboot ,您还可以使用以下全局配置来定义哪些所有域都可以访问您的后端。
@Configuration
public class MyConfiguration
@Bean
public WebMvcConfigurer corsConfigurer()
return new WebMvcConfigurerAdapter()
@Override
public void addCorsMappings(CorsRegistry registry)
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("PUT", "DELETE", "GET", "POST") //or allow all as you like
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
;
如果您仍然遇到问题,可能是因为 Spring Security 没有在您的 响应标头中添加像 Access-Control-Allow-Origin
这样的 CORS 标头。在这种情况下,您可以定义一个自定义 CORS 过滤器并将其添加到 spring 安全性,以便为所有 spring 安全性端点设置 CORS 响应标头。您可以像这样创建一个过滤器 bean:
public class CorsFilter implements Filter
@Override
public void init(FilterConfig filterConfig) throws ServletException
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request= (HttpServletRequest) servletRequest;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Credentials", true);
response.setHeader("Access-Control-Max-Age", 180);
filterChain.doFilter(servletRequest, servletResponse);
@Override
public void destroy()
方法二:
由于您使用的是 spring security,您还可以添加 CORS 配置以及 spring security,例如:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Override
protected void configure(HttpSecurity http) throws Exception
http.cors().and()
//other configurations that you want
@Bean
CorsConfigurationSource corsConfigurationSource()
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
//or any domain that you want to restrict to
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
//Add the method support as you like
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
据我所知,即使您在方法 1 中提供 CORS 配置,Spring security 也会占用它。但是,在 Spring 文档中,他们也提供了这种向 Spring Security 注册 CORS 的方式。
在您附加的 控制台日志 中,据说由于返回的 http 状态不正常,飞行前检查失败。所以,您可以尝试像方法 2 一样注册 cors 并使用过滤器添加以便在响应中正确添加标题。访问登录页面时,Springboot 正在阻止飞行前检查。您需要使用 spring security 正确设置您的 cors,以允许从不同的端口访问登录页面。
确认您的登录页面 /login
映射允许 CORS
官方Doc 参考Doc
【讨论】:
我尝试了所有方法。但结果是一样的。只有登录api无法通过react访问 在您附加的控制台日志中,据说由于返回的 http 状态不正常,飞行前检查失败。所以,您可以尝试像方法 2 一样注册 cors 并添加一个过滤器标头作为响应正确添加。访问登录页面时,Springboot 正在阻止飞行前检查。您需要使用 spring security 正确设置您的 cors,以允许从不同的端口访问登录页面。 然后它说:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。 在 springboot 响应头中设置以下内容,它应该可以工作:Access-Control-Allow-Origin 在我上面的回答中,我提供了如何创建自定义 CORS 过滤器,只需在您的 spring 安全配置中注册 CORS 过滤器。在这种情况下,某些浏览器(如 edge)有时不会将 * 识别为来源尝试将localhost:3000 添加到您的来源列表。以上是关于Spring Boot 中的 CORS 策略冲突的主要内容,如果未能解决你的问题,请参考以下文章
CORS 策略错误 - 使用 Spring Boot + React 发现 api
Angular 6 + Spring Boot:错误:“来自原点 'http://localhost:4200' 已被 CORS 策略阻止”
Spring Boot:即使使用@CrossOrigin,CORS 策略也阻止了从源 FRONTEND 访问 BACK_END' 处的 XMLHttpRequest
使用 axios 从 react js 调用 Spring Boot get 方法时,浏览器显示“请求已被 CORS 策略阻止”
CORS 策略:请求的资源 Spring Boot Rest API 和 VUE 上不存在“Access-Control-Allow-Origin”标头