Spring Security CORS 对于 Http PUT 方法无法工作

18

当我在Postman中尝试使用PutMapping API时,出现“Invalid CORS请求”的错误提示。但是对于“POST”和“GET”映射,则正常工作。

为什么“PUT”操作不起作用?

我的Spring Boot版本是2.0。

这是我的配置:

@Override
protected void configure(HttpSecurity http) throws Exception {




    http.cors().and().csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers("/h2-console/**/**").permitAll()
            .antMatchers(HttpMethod.GET,"/user/get-request").permitAll()
            .antMatchers(HttpMethod.POST,"/user/post-request").permitAll()
            .antMatchers(HttpMethod.PUT,"/user/put-request").permitAll()
            .and()
            .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
            .and()
            .addFilter(new JwtAuthenticationFilter(authenticationManager()))
            .addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtUserDetailService));




}


@Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").exposedHeaders("Authorization");

            }
        };
    }

这是我的控制器:

@RestController
@RequestMapping("/user")
public class UserController {

@PutMapping("/put-request")
public void doResetPassword(@RequestBody String password) {
    System.out.println("PUT MAPPING");


}

@PostMapping("/post-request")
public void doResetPassword(@RequestBody String password) {
    System.out.println("POST MAPPING");


}

@GetMapping("/get-request")
public void doResetPassword() {
    System.out.println("GET MAPPING");


}

}

1
对于忽略请求方法检查,您可以添加以下内容: .allowedMethods("*") - Amir Azizkhani
6个回答

18
@Configuration
public class CrossOriginConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry
                        .addMapping("/**")
                        .allowedMethods("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS");
            }
        };
    }

}

2
这个可行!而且比被接受的解决方案简单多了。谢谢! - slappyjam
1
感谢提供更简单的解决方案,请接受此答案! - Y.Kaan Yılmaz
1
经过数天的搜索,这个方法终于奏效了!!谢谢。 - Jalil.Jarjanazy

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

我通过添加这个bean成功允许了CORS请求。您可以根据需要配置setAllowedHeaders()和setExposedHeaders()。

此外,我在我的控制器中添加了这行代码;

@RequestMapping(value = "/auth")
@RestController
@CrossOrigin(origins = "*") //this line
public class AuthenticationController {..}

如果您的控制器需要处理即时的OPTION请求,您可以在控制器中添加此方法。您可以通过您的端点配置该值。

@RequestMapping(value = "/**/**",method = RequestMethod.OPTIONS)
public ResponseEntity handle() {
    return new ResponseEntity(HttpStatus.OK);
}

谢谢,这个注解解决了问题 '@CrossOrigin(origins = "*")',但我很困惑为什么我们需要它,因为我们已经在配置类中指定了origins。 - Samet Baskıcı
我还有一个关于这个注解的问题:'@RequestMapping(value = "//",method = RequestMethod.OPTIONS)',它适用于哪种场景? - Samet Baskıcı
我不是专家,但我认为我们需要映射哪些端点允许跨源请求。因此,我们需要在控制器上放置@CrossOrigin注释。希望有专业知识的人能够解释一下。 - Y.Kaan Yılmaz
这告诉Spring Boot请求可以来自任何来源,这可能会导致安全漏洞。 - Jp Silver
@JpSilver 这只是为了开发环境。 - Y.Kaan Yılmaz
显示剩余3条评论

0

我只想添加三件事。

  1. 接受的答案和下面的答案都不是CORS执行的正确方法。 如果您正在尝试配置CORS,那意味着您正在尝试仅使已知数量的客户端可以访问您的API。以下代码行

    configuration.setAllowedOrigins(ImmutableList.of("*")); // from the first answer
    
    .addMapping("/**") // from the second answer
    

    将API开放给任何客户端。如果这正是您想要的,那么您只需要执行以下操作就不需要再配置另一个bean了:

    http.cors().disable()
    
  2. 问题可能出现在您允许使用http来源并且使用https进行请求时。因此,请注意这两者之间的差异。

  3. 以下是可行的配置

    // 在import部分
    import static org.springframework.security.config.Customizer.withDefaults;
    
    // 在HttpSecurity配置中
    http.cors(withDefaults())
    
     @Bean
     public CorsConfigurationSource corsConfigurationSource() {
       final CorsConfiguration configuration = new CorsConfiguration();
       configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200", "https://localhost:4200"));
       configuration.setAllowedMethods(Arrays.asList("HEAD",
             "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
       configuration.setAllowCredentials(true);
       configuration.setAllowedHeaders(Arrays.asList("Content-Type", "X-Auth-Token","Authorization","Access-Control-Allow-Origin","Access-Control-Allow-Credentials"));
       configuration.setExposedHeaders(Arrays.asList("Content-Type", "X-Auth-Token","Authorization","Access-Control-Allow-Origin","Access-Control-Allow-Credentials"));
       final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
       source.registerCorsConfiguration("/**", configuration);
       return source;
     }
    

0
在使用 Kotlin 的 Spring 中,我做了以下操作:
@Bean
fun corsConfigurationSource(): CorsConfigurationSource? {
    val source = UrlBasedCorsConfigurationSource()

    val corsConfig = CorsConfiguration()
        .applyPermitDefaultValues()
        .setAllowedOriginPatterns(listOf("*"))
    corsConfig.addAllowedMethod(HttpMethod.PUT)
    source.registerCorsConfiguration("/**", corsConfig)

    return source
}

0

0

我正在使用Spring SecuritySpring Boot 2.1.2。在我的特定情况下,在CorsConfigurationSource bean的setAllowedMethods()中显式声明“PUT”方法后,PUT调用起作用了。头可以根据应用程序行为进行选择。

@Bean
CorsConfigurationSource corsConfigurationSource() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final String headers =  "Authorization, Access-Control-Allow-Headers, "+
                            "Origin, Accept, X-Requested-With, Content-Type, " + 
                            "Access-Control-Request-Method, Custom-Filter-Header";
    
    CorsConfiguration config = new CorsConfiguration();

    config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE")); // Required for PUT method
    config.addExposedHeader(headers);
    config.setAllowCredentials(true);
    config.applyPermitDefaultValues();
    
    source.registerCorsConfiguration("/**", config);
    
    return source;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接