Angular 6-Spring MVC ::选项预检请求引发500个内部服务器错误

时间:2019-12-04 06:04:03

标签: java spring-mvc cors angular6 preflight

意图:
使用Angular中的REST API,该API通过基于SpringMVC的Web应用程序公开。两者都在不同的主机上运行

问题

尽管我要请求的API是一个GET请求,但Angular 幕后首先会向REST API SpringMVC服务器发出一个OPTIONS请求。这样会抛出500服务器错误(请参见下面的CURL输出)。

尝试使用邮递员工具(GET请求)访问相同的API,令人惊讶的是,它给出了所需的输出(即也提供了Access-Control-Allow-Origin标头),没有错误,但是OPTIONS请求抛出了500个服务器错误。

我正在使用的技术堆栈

  • Angular 6(在NodeJS上方运行)
  • Spring MVC 4.3.6.RELEASE(已明确配置 Spring安全性 )[ Java config 基于Spring的配置]
  • Jetty-Runner 9.4.1(用于运行Spring MVC Web应用程序的WAR文件)。

Angular收到的错误消息:

Access to XMLHttpRequest at 'http://localhost:8080/v1/create' from origin
 'http://localhost:4200' 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.

代码段:

角度代码:

public createDomainObj() {           
    return this.http.post('http://localhost:8080/v1/create', request body parameter)
}

SpringMVC代码:

@ResponseBody
@RequestMapping(value = "/v1/create", method = RequestMethod.POST)
@AccessController(accessLevel = "Anonymous")
public <APIResponseModelClass> anAPIMethod(@RequestBody param1, param2) {
    //code logic 
    return <obj>;
}

已经尝试了什么:

SpringMVC中的CORS过滤器,注释的所有组合,但是没有运气。

还尝试了以下链接中提到的建议,但没有成功:

https://www.baeldung.com/spring-security-cors-preflight

How to add Access-Control-Allow-Origin to jetty server

CURL能够重现该问题:

请求

curl -H "Origin:*" -H "Access-Control-Request-Method: GET, POST, PUT, DELETE" 
-H "Access-Control-Request-Headers: X-Requested-With" 
-X OPTIONS --verbose  http://localhost:8080/v1/create

响应

Trying 127.0.0.1...
 Connected to localhost (127.0.0.1) port 8080 (#0)
 OPTIONS /v1/create HTTP/1.1
 Host: localhost:8080
 User-Agent: curl/7.47.0
 Accept: */*
 Origin:*
 Access-Control-Request-Method: GET, POST, PUT, DELETE
 Access-Control-Request-Headers: X-Requested-With
 Content-Length: 392
 Content-Type: application/x-www-form-urlencoded

 upload completely sent off: 392 out of 392 bytes
 HTTP/1.1 500 Server Error
 Connection: close
Server: Jetty(9.4.2.v20170220)
Closing connection 0


因此,如何使Angular从具有OPTIONS预检方面的SpringMVC中使用REST API?

1 个答案:

答案 0 :(得分:0)

我可以谈谈问题, CORS:Response to preflight request doesn't pass access control
有两种类型的请求,
1)简单
有一些条件,可以轻松交换cors标头,允许的方法,标头,内容类型
2)飞行前
那些不符合简单请求条件的条件是预检,例如,
我们向服务器发送DELETE请求。浏览器发送带有标题的OPTIONS请求,该标题包含有关我们提出的DELETE请求的信息。

OPTIONS /users/:id 
Access-Control-Request-Method: DELETE 

要解决的简单问题是,您可以删除或更改不需要的任何复杂标头。

Header set Access-Control-Allow-Origin "*"设置此选项将适用于简单的CORS请求,因此对于具有自定义标头值的更复杂的请求将不起作用,这就是浏览器的预检机制,它检查服务是否接受请求,
记住,其中包括

Access-Control-Request-Headers
Access-Control-Request-Method
Access-Control-Allow-Origin

似乎您需要在http configure thats cors过滤器中添加cors, 启用cors的不同方法,
1)控制器方法CORS配置

  @CrossOrigin(origins = "http://localhost:9000")
  @GetMapping("/greeting")
  public Greeting greeting(@RequestParam(required=false, defaultValue="World") String name) {
    System.out.println("==== in greeting ====");
    return new Greeting(counter.incrementAndGet(), String.format(template, name));
  }

2)全局CORS配置

  public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
      @Override
      public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:9000");
      }
    };
  }

3)启用webSecurity,尝试添加http.cors()

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // ...
        http.cors();
    }
}