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

查看:28
本文介绍了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,但是您的 react 在本地的端口 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.

方法一:

您可以通过使用以下注释来解决这个问题:

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 Security 没有在您的 中添加 CORS 标头,例如 Access-Control-Allow-Origin>响应头.在这种情况下,您可以定义自定义 CORS 过滤器并将其添加到 spring 安全性,以便为所有 spring 安全性端点设置 CORS 响应标头.您可以创建一个过滤器 bean,如:

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() {

    }
}

方法二:

由于您使用的是 spring security,您还可以添加 CORS 配置以及 spring security,例如:

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 安全性注册 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 Security 正确设置 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

官方文档参考 Doc

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

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