Java Spring 控制器拒绝除 GET 之外的所有请求

Posted

技术标签:

【中文标题】Java Spring 控制器拒绝除 GET 之外的所有请求【英文标题】:Java Spring controler refuses all requests expect GET 【发布时间】:2020-07-21 02:37:41 【问题描述】:

我正在开发带有 Angular 前端的 Java Spring 应用程序,但我遇到了没有你的帮助我无法解决的问题。当我从 Angular 向 Java 发出请求时,只有 GET 会通过,但 POST、DELETE 和 POST 会返回以下错误

从源“http://localhost:4200”访问“http://localhost:8080/patient”处的 XMLHttpRequest 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头。

控制器

@Controller
@RequestMapping("/patient")
@CrossOrigin(origins = "*", maxAge = 3600)
public class PatientController 

    private PatientService patientService;

    @Autowired
    public PatientController(PatientService patientService) 
        this.patientService = patientService;
    

    @GetMapping
    public ResponseEntity<Iterable<Patient>> getPatient() 
        return new ResponseEntity<>(patientService.findAll(), HttpStatus.OK);
    

    @PostMapping
    public ResponseEntity<Iterable<Patient>> postPatient() 
        return new ResponseEntity<>(patientService.findAll(), HttpStatus.OK);
    

    @PutMapping
    public ResponseEntity<Iterable<Patient>> putPatient() 
        return new ResponseEntity<>(patientService.findAll(), HttpStatus.OK);
    

    @DeleteMapping
    public ResponseEntity<Iterable<Patient>> deletePatient() 
        return new ResponseEntity<>(patientService.findAll(), HttpStatus.OK);
    


角度服务

  getPatients() 
    this.http.post(AppComponent.apiUrl + '/patient', this.httpOptions) 
      .subscribe(data => 
        console.log(data);
      );
  

proxy.conf.json

 "/api*": 
    "target":"http://localhost:8080",
    "secure":false,
    "logLevel":"debug",
    "changeOrigin": true 
   

提前感谢您!

【问题讨论】:

您的proxy.conf.json 是否包含"changeOrigin": true 值? 是的,我添加了这个字段,但没有帮助。现在我的代理配置看起来像这样: "/api*": "target":"http://localhost:8080", "secure":false, "logLevel":"debug", "changeOrigin": true 这些端点是否对来自同一台机器的简单 curl(或其他一些客户端,如 postman)请求作出反应? 【参考方案1】:

@CrossOrigin注解中不需要设置origins=*,默认允许所有来源。

您尝试将注释放在方法级别?

【讨论】:

如您所见,注释也添加到类级别以及 origins 参数。是的,我也尝试在方法级别设置它,但没有成功。【参考方案2】:

你可以试试这个:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class CorsConfig implements WebMvcConfigurer 

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**")
                .allowedOrigins("https://localhost:4200")
                .allowCredentials(true);
    


并确保您的 Angular 客户端发送他的凭据:

httpOptions = 
  withCredentials: true,
  ...

【讨论】:

关闭,我也找到了这种方法的解决方案,但我还需要添加allowedMethods("*")allowedHeaders("*")【参考方案3】:

好吧,我解决了这个问题。

我不知道为什么,但是对于此类问题非常流行的解决方案 CORS Fitler 并没有改变任何代理配置,但是将 CorsConfigurationSource bean 和以下行添加到 configure 方法解决了问题。

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 

    //Controlling access
    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.authorizeRequests()
                ...
                .and()
                .cors()      
    

    @Bean
    CorsConfigurationSource corsConfigurationSource() 
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Collections.singletonList("*"));
        configuration.setAllowedMethods(Collections.singletonList("*"));
        configuration.setAllowedHeaders(Collections.singletonList("*"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    

另外对我有用的第二个是添加以下类:

@Configuration
public class WebConfiguration implements WebMvcConfigurer 

        @Override
        public void addCorsMappings(CorsRegistry registry) 
            registry
                    .addMapping("/**")
                    .allowedMethods("*")
                    .allowedHeaders("*")
                    .allowedOrigins("*")
                    .allowCredentials(false);
        

但在此解决方案中,将.and().cors() 行添加到安全配置中也是必要

【讨论】:

【参考方案4】:

这是 Angular 的一个非常烦人的配置。仅仅允许交叉起源是不够的。您还需要允许方法和一些标头。这个配置帮助了我:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer 

  @Value("$angular")
  private String angularOrigin;

  @Bean
  public WebMvcConfigurer corsConfigurer()
    return new WebMvcConfigurer() 
      @Override
      public void addCorsMappings(CorsRegistry registry) 
        registry
            .addMapping("/**")
            .allowedOrigins(angularOrigin)
            .allowedHeaders("Authorization", "Cache-Control", "Content-Type", "Accept", "X-Requested-With", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Origin")
            .exposedHeaders("Access-Control-Expose-Headers", "Authorization", "Cache-Control", "Content-Type", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Origin")
            .allowedMethods("PUT","GET","POST","DELETE","OPTIONS");
      
    ;
  

还要注意应该允许一个 OPTION HTTP 方法。

【讨论】:

以上是关于Java Spring 控制器拒绝除 GET 之外的所有请求的主要内容,如果未能解决你的问题,请参考以下文章

拒绝访问除索引文件之外的所有文件 - Apache2

Postgres:除 phpPgAdmin 之外的所有权限都被拒绝

拒绝除一个之外的所有存储桶的 AWS IAM 策略

拒绝直接访问除 index.php 之外的所有 .php 文件

拒绝除特定范围之外的所有 IP 访问 AWS S3

在 Spring 安全性中允许除一个之外的所有 URL