我是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;
}
}
我遇到了这个问题,我确实需要一些帮助。我已经尝试了在stackoverflow中给出的一些答案,类似于我的问题。但这并不能解决我的问题。 Mt spring boot版本是2.1.4
答案 0 :(得分:4)
您正面临这个问题,因为您已经允许在8080端口的后端启用cors,但是您的反应在本地的3000端口上进行了。因此,springboot将不接受该请求,因为该请求来自其他端口地址。
方法1:
您可以通过使用像这样的注释来解决:
@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安全未在响应标头中添加Access-Control-Allow-Origin
之类的CORS标头。在这种情况下,您可以定义一个自定义的CORS过滤器并将其添加到Spring Security中,以便为所有Spring Security端点设置CORS响应标头。您可以创建一个滤豆,如:
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() {
}
}
方法2:
由于您正在使用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那样提供,Spring security仍会占用CORS配置。但是,在spring文档中,Spring Security也提供了向Spring Security注册CORS的这种方式。
在您随附的控制台日志中,据说由于返回http状态而导致飞行前检查失败是不正常的。因此,您可以尝试像方法2那样注册cors并使用过滤器吗?添加,以便响应中正确添加标头。访问登录页面时,Springboot会阻止飞行前检查。您需要使用spring安全性正确设置cors设置,以允许从其他端口访问登录页面。
确认您的登录页面/login
映射已允许CORS
答案 1 :(得分: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;
}