2016-07-21 14 views
6

Trong khi gỡ lỗi vấn đề CORS tôi gặp phải, tôi đã tìm thấy hành vi sau. Chrome làm cho các tùy chọn sau preflight yêu cầu (viết lại bằng CURL chính Chrome):Yêu cầu preflight CORS không thành công do tiêu đề chuẩn

curl -v 'https://www.example.com/api/v1/users' -X OPTIONS -H 'Access-Control-Request-Method: POST' -H 'Origin: http://example.com' -H 'Accept-Encoding: gzip,deflate,sdch' -H 'Accept-Language: es-ES,es;q=0.8,en;q=0.6' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://example.com/users/new' -H 'Connection: keep-alive' -H 'Access-Control-Request-Headers: accept, x-api-key, content-type' 

Các phản hồi từ máy chủ để yêu cầu này nếu như sau:

< HTTP/1.1 403 Forbidden 
< Date: Thu, 21 Jul 2016 14:16:56 GMT 
* Server Apache/2.4.7 (Ubuntu) is not blacklisted 
< Server: Apache/2.4.7 (Ubuntu) 
< X-Content-Type-Options: nosniff 
< X-XSS-Protection: 1; mode=block 
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate 
< Pragma: no-cache 
< Expires: 0 
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains 
< X-Frame-Options: SAMEORIGIN 
< Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH 
< Content-Length: 20 
< Keep-Alive: timeout=5, max=100 
< Connection: Keep-Alive 

là phần thân của phản ứng 'không hợp lệ Yêu cầu của CORS '. Nếu tôi lặp lại yêu cầu loại bỏ các tiêu đề 'Access-Control-Yêu cầu-Phương pháp' (và duy nhất mà tiêu đề) các yêu cầu OPTIONS thành công với các phản ứng sau:

< HTTP/1.1 200 OK 
< Date: Thu, 21 Jul 2016 14:21:27 GMT 
* Server Apache/2.4.7 (Ubuntu) is not blacklisted 
< Server: Apache/2.4.7 (Ubuntu) 
< X-Content-Type-Options: nosniff 
< X-XSS-Protection: 1; mode=block 
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate 
< Pragma: no-cache 
< Expires: 0 
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains 
< X-Frame-Options: SAMEORIGIN 
< Access-Control-Allow-Headers: origin, content-type, accept, x-requested-with, x-api-key 
< Access-Control-Max-Age: 60 
< Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS 
< Access-Control-Allow-Origin: * 
< Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH 
< Content-Length: 0 
< Keep-Alive: timeout=5, max=100 
< Connection: Keep-Alive 

Tuy nhiên, tiêu đề vi phạm là một CORS spec standard header vì thế nên không ngăn yêu cầu thành công, đúng không? Tại sao tiêu đề này lại gây ra hành vi như vậy?

Và làm cách nào để tinh chỉnh tiêu đề kiểm soát truy cập được gửi bởi máy chủ của tôi để yêu cầu hoạt động khi được thực hiện với Chrome?

Nhân tiện, tôi đang sử dụng Chrome 36.0 và máy chủ đang sử dụng Khởi động mùa xuân, với tiêu đề CORS do Spring quản lý.

Khi yêu cầu được thực hiện bởi Firefox (v47.0), hành vi khác nhau nhưng với kết quả tương tự. Firefox thậm chí không gửi yêu cầu preflight, nó gửi trực tiếp yêu cầu POST, nhận được phản hồi 403 Forbidden. Tuy nhiên, nếu tôi sao chép yêu cầu bằng tùy chọn 'Sao chép dưới dạng cURL' và lặp lại yêu cầu đó từ cửa sổ đầu cuối, Nó sẽ gửi thành công tiêu đề CORS chính xác trong phản hồi.

Bất kỳ ý tưởng nào?

Cập nhật: Firefox gửi yêu cầu OPTIONS preflight (như được hiển thị bởi plugin tiêu đề HTTP Live), nhưng Firebug mặt nạ nó, vì vậy hành vi trong cả hai trình duyệt chính xác như nhau. Trong cả hai trình duyệt là tiêu đề 'Access-control-request-method' sự khác biệt khiến yêu cầu thất bại.

Trả lời

14

Sau rất nhiều khó khăn, cuối cùng tôi đã tìm thấy sự cố. Tôi cấu hình một ánh xạ yêu cầu trong mùa xuân để xử lý OPTIONS giao thông, như thế này:

@RequestMapping(value= "/api/**", method=RequestMethod.OPTIONS) 
public void corsHeaders(HttpServletResponse response) { 
    response.addHeader("Access-Control-Allow-Origin", "*"); 
    response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); 
    response.addHeader("Access-Control-Allow-Headers", "origin, content-type, accept, x-requested-with"); 
    response.addHeader("Access-Control-Max-Age", "3600"); 
} 

Tôi không biết rằng theo mặc định Spring sử dụng một default CORS processor, và có vẻ như nó đã được can thiệp vào bản đồ yêu cầu của tôi. Việc xóa ánh xạ yêu cầu của tôi và thêm chú thích @CrossOrigin vào ánh xạ yêu cầu thích hợp đã giải quyết được sự cố.

+2

Có, chuyến đi đầu tiên, Spring có bộ xử lý cors mặc định, nhưng trừ khi cấu hình của nó, nó actuall y ngắt xử lý CORS bình thường nếu bạn đã thiết lập nó trong Apache. Dường như bạn phải cấu hình một CorsFilter, hoặc làm theo lời khuyên ở đây - https://spring.io/guides/gs/rest-service-cors/ – chrismarx

+1

Tôi thấy bài viết này hữu ích là tốt: http://stackoverflow.com/câu hỏi/9521690/how-to-xử lý-http-tùy chọn-với-spring-mvc DispatchServlet phải được cấu hình để vượt qua cùng tùy chọn theo yêu cầu, hoặc nếu không nó không bao giờ đạt yêu cầu ánh xạ: ... < servlet-name> yourServlet org.springframework.web.servlet.DispatcherServlet dispatchOptionsRequest true 1 ... – Mike

0

Tôi đã thêm câu trả lời này làm câu trả lời vì tôi không thể định dạng câu trả lời cho câu trả lời bình chọn hàng đầu.

tôi tìm thấy bài này hữu ích cũng như: How to handle HTTP OPTIONS with Spring MVC?

DispatchServlet phải được cấu hình để vượt qua cùng tùy chọn theo yêu cầu, hoặc nếu không nó không bao giờ đạt yêu cầu ánh xạ:

... 
    <servlet> 
    <servlet-name>yourServlet</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>dispatchOptionsRequest</param-name> 
     <param-value>true</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 
... 
0

tôi đã cùng một vấn đề. Tôi đã giải quyết nó bằng cách thêm 'OPTIONS' vào các phương thức CORS được cho phép trong cấu hình Spring MVC của tôi.

@Configuration 
@EnableWebMvc 
@ComponentScan 
public class RestApiServletConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void addCorsMappings(CorsRegistry registry) { 
     super.addCorsMappings(registry); 
     registry.addMapping("/**") 
       .allowedOrigins("http://localhost:3000", "http://localhost:8080") 
       .allowedMethods("GET", "PUT", "POST", "DELETE", "OPTIONS"); 
    } 
} 
0

tôi cũng phải đối mặt với cùng một vấn đề và tìm giải pháp cho phép vấn đề CORS toàn cầu trong khởi động mùa xuân

@Configuration 
@EnableWebMvc 
public class WebConfig extends WebMvcConfigurerAdapter { 
    @Override 
    public void addCorsMappings(CorsRegistry registry) { 
     registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*") 
       .allowedHeaders("*"); 
    } 
} 

sau này, chúng ta cần phải kích hoạt CORS trong mức độ bảo mật mùa xuân cũng nên cho tiện ích này cors() trong lớp SecurityConfiguration của bạn, trong đó mức độ WebSecurityConfigurerAdapter

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

     httpSecurity 
       .cors() 
       .and() 
       .csrf().disable() 
       .authorizeRequests().. 

    } 
Các vấn đề liên quan