CORS 正在阻止 PUT、DELETE 和 POST 请求,但 GET 正在工作

Posted

技术标签:

【中文标题】CORS 正在阻止 PUT、DELETE 和 POST 请求,但 GET 正在工作【英文标题】:CORS is blocking PUT, DELETE, and POST requests but GET is working 【发布时间】:2021-11-19 19:24:27 【问题描述】:

我很茫然。我正在尝试配置CORS,并且我已经尝试了几乎所有可以在互联网/堆栈溢出上找到的东西。

请求在 Postman 中有效,但在使用 axios 的 React 中无效。

这是我删除用户的函数(这在 Postman 中有效,但在 React 中触发时无效):

 deleteEmployeeById(id) 
    // return axios.delete(API_BASE_URL + `employees/$id`);
    var testing = "";
    return axios
      .delete(API_BASE_URL + `employees/$id`, 
        headers: 
          Authorization: `Bearer $HARDCODED_JWT_TESTING`,
        ,
      )
      .then("yessssss")
      .catch((error) => 
        console.log("failed to delete  emp by id" + error);
      );
  

我有一个如下所示的 SecurityConfig.java 文件:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 
    @Autowired
    MyUserDetailsService myUserDetailsService;

    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        // TODO : use this line when i implement bcrypt
        // auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());
        auth.userDetailsService(myUserDetailsService);

    

    // TODO : should use this password encoder
    // public PasswordEncoder passwordEncoder() 
    // return new BCryptPasswordEncoder();
    // 

    @Bean
    public PasswordEncoder passwordEncoder() 
        // TODO : not secure. Use a different encoder. testing only
        return NoOpPasswordEncoder.getInstance();
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        // allow users to access "authenticate" page without being authenticated
        // all other requests must be authenticated
        // stateless tells it to not create a session? Do i need? Not sure yet
        // http.csrf().disable().authorizeRequests().antMatchers("/api/authenticate").permitAll().anyRequest()
        // .authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues()).and().csrf()
                .disable().authorizeRequests().antMatchers("/api/authenticate").permitAll().anyRequest().authenticated()
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

    

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception 
        // create bean of type 'authenticationManager'
        return super.authenticationManagerBean();
    

    @Bean
    CorsConfigurationSource corsConfigurationSource() 
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setExposedHeaders(Arrays.asList("X-Auth-Token", "Authorization", "Access-Control-Allow-Origin",
                "Access-Control-Allow-Credentials"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    


我不知道错误在哪个函数中,但我认为它是 corsConfigurationSource() 方法。但是,我认为这不应该起作用。在我尝试为应用添加安全性之前,它曾经可以工作。

正如您在该方法中看到的那样,我已经设置了所有允许的方法,我允许所有来源等,但是在尝试从我的数据库中删除用户时仍然出现此错误:

Access to XMLHttpRequest at 'http://localhost:8080/api/employees/6151c89ea1b79f789a7a964b' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

这确实在 Postman 中工作。我可以删除用户没问题,它只是在我的前端 React 应用程序触发时不起作用。

看起来我允许CORS 中的所有内容,知道还有什么需要配置的吗??

【问题讨论】:

【参考方案1】:

在实例化CorsConfiguration 后,尝试删除SecurityConfig 中的.applyPermitDefaultValues() 调用。这基本上是将 CORS 配置重置为默认值:

允许所有具有 CORS 规范中定义的特殊值“*”的来源。仅当 origin 和 originPatterns 均未设置时才设置。 允许“简单”方法 GET、HEAD 和 POST。 允许所有标题。 将最大年龄设置为 1800 秒(30 分钟)。

另外,调用corsConfigurationSource() 方法而不是实例化一个新的CorsConfiguration

@Override
protected void configure(HttpSecurity http) throws Exception 
    http.cors().configurationSource(corsConfigurationSource()).and().csrf()
            .disable().authorizeRequests().antMatchers("/api/authenticate").permitAll().anyRequest().authenticated()
            .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

另外,更新您的CorsConfigurationSource 如下:

@Bean
CorsConfigurationSource corsConfigurationSource() 
    final CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
    configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
    configuration.setAllowCredentials(true);
    configuration.setAllowedHeaders(Arrays.asList("*"));
    configuration.setExposedHeaders(Arrays.asList("X-Auth-Token", "Authorization", "Access-Control-Allow-Origin",
            "Access-Control-Allow-Credentials"));
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;

【讨论】:

【参考方案2】:

为了更清楚和测试的目的,您可以尝试通过以下方法测试您的corsConfigurationSource()。 请根据您的应用程序更改代码,例如来源等。

@Bean
CorsConfigurationSource corsConfigurationSource() 
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
    configuration.setAllowedMethods(Arrays.asList("*"));
    configuration.setAllowedHeaders(Arrays.asList("*"));
    configuration.setAllowCredentials(true);
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;

它基本上允许所有标头、方法和来源。它不适合生产,但出于测试目的,您可以尝试一下。

【讨论】:

以上是关于CORS 正在阻止 PUT、DELETE 和 POST 请求,但 GET 正在工作的主要内容,如果未能解决你的问题,请参考以下文章

访问被 CORS 阻止的 XMLHttpRequest,请求的资源上不存在“Access-Control-Allow-Origin”标头,仅用于 PUT 和 DELETE API

Springboot 2.0.2 - 解决 PUT 和 DELETE 的 CORS

CORS 阻止 Expressjs 中的文件上传

使用具有多个来源的 PUT 和 DELETE 请求时如何解决 ASP.NET Web API CORS Preflight 问题?

无法在 JQuery 1.6.4 中使用 CORS 进行 PUT/POST/DELETE HTTP 调用

即使使用 Access-Control-Allow-Origin 也被 CORS 阻止的 API 调用:* 存在于标头中