Spring Boot中的CORS策略冲突 [英] CORS policy conflict in Spring boot

查看:66
本文介绍了Spring Boot中的CORS策略冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Spring Boot的新手,我使用Spring Boot实现了一些基本的REST api.当我尝试使用react调用那些api时,我在调用某些CORS策略时遇到了错误.然后,我找到了解决该问题的方法,并且除登录api调用之外,我所有的api端点均正常工作.我在调用时遇到了相同的错误:

I'm new to spring boot and I implemented some basic REST apis using spring boot. And when I tried to call those api using react I've got an error calling some CORS policies. Then I found a solution to that problem, And all my api end point working correctly except the login api call. I get the same error calling:

这是我的网络安全Java类.

Here is my web security java class.

@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;
    }
}

这是我的示例控制器类.

And here is my example controller class.

@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

I'm stuck with this problem and I really need some help. I've tried some answers given in stackoverflow as similar to my problem. But that didn't solve my problem. Mt spring boot version is 2.1.4

推荐答案

您正面临这个问题,因为,您允许在8080端口上使用后端的cors,但您的反应是在本地的3000端口上进行的.因此,springboot将不接受请求,因为它来自其他端口地址.

You are facing the issue because,you have allowed cors on your backend from port 8080, but your react is up in port 3000 on local.So , springboot will not accept the request as it is coming from a different port address.

方法1:

您可以通过使用像这样的注释来解决:

You could get away with this by using the annotation like :

@CrossOrigin(origins = "http://localhost:3000", maxAge = 3600)

由于您使用的是springboot,因此您还可以使用以下全局配置来定义哪些所有域都可以访问您的后端.

Since you are using springboot , you can also use the following global config to define which all domains have access to your backend.

@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响应标头.您可以创建一个像这样的滤豆:

and if you are still having issues , it might be because the spring security is not adding the CORS headers like Access-Control-Allow-Origin in your response header. In that case , you can define a custom CORS filter and add it to the spring security so that the CORS response headers are set for all spring security endpoints . You can create a filter bean like :

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:

因为您使用的是弹簧安全性,所以您还可以将CORS配置和弹簧安全性一起添加:

since you are using spring security you could also add the CORS configuration along with spring security like :

@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安全也将占用CORS配置.但是,在Spring文档中,Spring安全提供了这种向Spring安全注册CORS的方式.

Spring security will take up the CORS configuration even if you provide it like in method 1 as per my knowledge.But , in spring documentation they have provided this way of registering CORS with spring security as well.

在您随附的控制台日志中,说由于返回HTTP状态导致飞行前检查失败是不正确的.因此,您可以尝试像方法2一样注册cors并具有过滤器吗?添加,以便正确添加标头作为响应.访问登录页面时,Springboot会阻止飞行前检查.您需要使用spring安全性正确设置cors设置,以允许从其他端口访问登录页面.

In your console log that you have attached it is said that the pre flight check failed because of http status returned is not OK .So , can you try registering cors like method 2 and have a filter added so that the headers are added correctly in response. Springboot is blocking the pre flight check when the login page is accessed. You need to get your cors setup properly with the spring security to allow login page to be accessed from a dfferent port.

确认您的登录页面/login映射已允许CORS

Confirm that your login page /login mapping have CORS allowed

官方文档 参考文档

这篇关于Spring Boot中的CORS策略冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆