Java Spring控制器拒绝除了GET以外的所有请求。

huangapple go评论75阅读模式
英文:

Java Spring controler refuses all requests expect GET

问题

我正在开发使用Java Spring框架构建的应用程序,前端使用Angular,但我遇到了一个问题,没有您的帮助我无法解决。当我从Angular发起请求到Java时,只有GET请求是成功的,但是POST、DELETE和PUT请求返回以下错误:

跨源资源共享(CORS)策略阻止了从源 'http://localhost:4200' 发起的 XMLHttpRequest 到 'http://localhost:8080/patient' 的请求。所请求的资源上没有 '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);
    }
}

Angular 服务

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

提前感谢您的帮助!

英文:

I am working on Java Spring application with frontend on Angular but I faced issue that I can't resolve without yours help. When I am making requests from Angular to Java only GET ones are passing but POST, DELETE and POST return following error

>Access to XMLHttpRequest at 'http://localhost:8080/patient' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Controler

@Controller
@RequestMapping(&quot;/patient&quot;)
@CrossOrigin(origins = &quot;*&quot;, maxAge = 3600)
public class PatientController {

    private PatientService patientService;

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

    @GetMapping
    public ResponseEntity&lt;Iterable&lt;Patient&gt;&gt; getPatient() {
        return new ResponseEntity&lt;&gt;(patientService.findAll(), HttpStatus.OK);
    }

    @PostMapping
    public ResponseEntity&lt;Iterable&lt;Patient&gt;&gt; postPatient() {
        return new ResponseEntity&lt;&gt;(patientService.findAll(), HttpStatus.OK);
    }

    @PutMapping
    public ResponseEntity&lt;Iterable&lt;Patient&gt;&gt; putPatient() {
        return new ResponseEntity&lt;&gt;(patientService.findAll(), HttpStatus.OK);
    }

    @DeleteMapping
    public ResponseEntity&lt;Iterable&lt;Patient&gt;&gt; deletePatient() {
        return new ResponseEntity&lt;&gt;(patientService.findAll(), HttpStatus.OK);
    }

}

Angular service

  getPatients() {
    this.http.post(AppComponent.apiUrl + &#39;/patient&#39;, this.httpOptions) 
      .subscribe(data =&gt; {
        console.log(data);
      });
  }

proxy.conf.json

{ &quot;/api*&quot;: {
    &quot;target&quot;:&quot;http://localhost:8080&quot;,
    &quot;secure&quot;:false,
    &quot;logLevel&quot;:&quot;debug&quot;,
    &quot;changeOrigin&quot;: true 
   }
}

Thank you in advance!

答案1

得分: 0

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

你尝试将注解放在方法级别吗?

英文:

Not need to set origins=* in @CrossOrigin annotation, by default all origins are permited.

You tried to put the annotation at method level?

答案2

得分: 0

您可以尝试这样做

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,
  ...
}

<details>
<summary>英文:</summary>

You could try this:

    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(&quot;/**&quot;)
    				.allowedOrigins(&quot;https://localhost:4200&quot;)
    				.allowCredentials(true);
    	}
    
    }

And make sure that your angular client sends his credentials:

    httpOptions = {
      withCredentials: true,
      ...
    }

</details>



# 答案3
**得分**: 0

Well, I resolved the issue.

I don't know why but CORS Filter, which is a quite popular resolution for issues like that, didn't change anything, neither did the proxy config. However, adding a CorsConfigurationSource bean and the following lines to the `configure` method resolved the problem.

**SecurityConfig.java**
```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;
    }
}

Another solution that worked for me was adding the following class:

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

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

But in this solution, it is also essential to add .and().cors() lines into the security config.

英文:

Well, I resolved the issue.

I don't know why but CORS Fitler that is quite popular resolution for issues like that doesn't changed anything neiher the proxy config but adding CorsConfigurationSource bean and following lines to configure method resolved the problem.

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(&quot;*&quot;));
        configuration.setAllowedMethods(Collections.singletonList(&quot;*&quot;));
        configuration.setAllowedHeaders(Collections.singletonList(&quot;*&quot;));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration(&quot;/**&quot;, configuration);
        return source;
    }
}

Also the second one which was working for me was to add a following class:

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry
                    .addMapping(&quot;/**&quot;)
                    .allowedMethods(&quot;*&quot;)
                    .allowedHeaders(&quot;*&quot;)
                    .allowedOrigins(&quot;*&quot;)
                    .allowCredentials(false);
        }
}

But in this solution is also essential to add .and().cors() lines into security config.

答案4

得分: 0

这是一个非常烦人的 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 方法。

英文:

This is a very annoying configuration of Angular. Just allowing cross origins wouldn't be enough. You also would need to allow methods and some headers. This configuration helped me:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

  @Value(&quot;${angular}&quot;)
  private String angularOrigin;

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

Also notice that there is an OPTION HTTP method that should be allowed.

huangapple
  • 本文由 发表于 2020年4月8日 23:53:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/61104834.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定