2017-02-03 19 views
5

Tôi đã tạo hai ứng dụng web - ứng dụng khách và dịch vụ.
Sự tương tác giữa ứng dụng khách và dịch vụ diễn ra tốt đẹp khi chúng được triển khai trong cùng một cá thể Tomcat.
Nhưng khi các ứng dụng được triển khai vào các phiên bản Tomcat riêng biệt (các máy khác nhau), tôi nhận được lỗi dưới đây khi yêu cầu gửi ứng dụng dịch vụ.Vấn đề về CORS - Không có tiêu đề 'Access-Control-Allow-Origin' có trên tài nguyên được yêu cầu

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 401 

Ứng dụng khách của tôi sử dụng JQuery, HTML5 và Bootstrap.

gọi AJAX được thực hiện để phục vụ như hình dưới đây:

var auth = "Basic " + btoa({usname} + ":" + {password}); 
var service_url = {serviceAppDomainName}/services; 

if($("#registrationForm").valid()){ 
    var formData = JSON.stringify(getFormData(registrationForm)); 
    $.ajax({ 
     url: service_url+action, 
     dataType: 'json', 
     async: false, 
     type: 'POST', 
     headers:{ 
      "Authorization":auth 
     }, 
     contentType: 'application/json', 
     data: formData, 
     success: function(data){ 
      //success code 
     }, 
     error: function(jqXhr, textStatus, errorThrown){ 
      alert(errorThrown); 
     }); 
} 

ứng dụng dịch vụ của tôi sử dụng Spring MVC, Spring liệu JPA và Xuân An.

Tôi đã bao gồm CorsConfiguration lớp như hình dưới đây:

CORSConfig.java:

@Configuration 
@EnableWebMvc 
public class CORSConfig extends WebMvcConfigurerAdapter { 
    @Override 
    public void addCorsMappings(CorsRegistry registry) { 
     registry.addMapping("*"); 
    } 
} 

SecurityConfig.java:

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
@EnableWebSecurity 
@ComponentScan(basePackages = "com.services", scopedProxy = ScopedProxyMode.INTERFACES) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    @Qualifier("authenticationService") 
    private UserDetailsService userDetailsService; 

    @Bean 
    @Override 
    public AuthenticationManager authenticationManagerBean() throws Exception { 
     return super.authenticationManagerBean(); 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(userDetailsService); 
     auth.authenticationProvider(authenticationProvider()); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
       .authorizeRequests() 
       .antMatchers("/login").permitAll() 
       .anyRequest().fullyAuthenticated(); 
     http.httpBasic(); 
     http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); 
     http.csrf().disable(); 
    } 

    @Bean 
    public PasswordEncoder passwordEncoder() { 
     return new BCryptPasswordEncoder(); 
    } 

    @Bean 
    public DaoAuthenticationProvider authenticationProvider() { 
     DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); 
     authenticationProvider.setUserDetailsService(userDetailsService); 
     authenticationProvider.setPasswordEncoder(passwordEncoder()); 
     return authenticationProvider; 
    } 
} 

Xuân An phụ thuộc:

<dependency> 
      <groupId>org.springframework.security</groupId> 
      <artifactId>spring-security-config</artifactId> 
      <version>3.2.3.RELEASE</version> 
</dependency> 
<dependency> 
      <groupId>org.springframework.security</groupId> 
      <artifactId>spring-security-web</artifactId> 
      <version>3.2.3.RELEASE</version> 
</dependency> 

Tôi đang sử dụng máy chủ Apache Tomcat để triển khai . yêu cầu preflight

Trả lời

6

CORS' sử dụng HTTP OPTIONS mà không cần thông tin, xem Cross-Origin Resource Sharing:

Nếu không, làm cho một preflight yêu cầu. Fetch URL yêu cầu từ nguồn gốc nguồn gốc sử dụng nguồn giới thiệu như là nguồn override giới thiệu với các chuyển hướng lá cờ bằng tay và các thiết lập khối cookie cờ, sử dụng các tùy chọn phương pháp, và với những hạn chế bổ sung sau đây:

  • Bao gồm một Access-Control -Request-Method header với giá trị của trường header, phương thức yêu cầu (ngay cả khi đó là một phương thức đơn giản).
  • Nếu tiêu đề yêu cầu tác giả không trống bao gồm tiêu đề Access-Control-Request-Headers với giá trị trường tiêu đề, danh sách được phân cách bằng dấu phẩy của tên trường tiêu đề từ tiêu đề yêu cầu tác giả theo thứ tự từ điển, mỗi tiêu đề được chuyển đổi thành chữ thường ASCII (thậm chí khi một hoặc nhiều tiêu đề đơn giản).
  • Loại trừ tiêu đề yêu cầu tác giả.
  • Loại trừ thông tin đăng nhập của người dùng.
  • Loại trừ phần thân yêu cầu.

Bạn phải cho phép truy cập ẩn danh cho HTTP OPTIONS.

sửa đổi (và đơn giản hóa) Mã của bạn:

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http 
     .authorizeRequests() 
      .andMatchers(HttpMethod.OPTIONS, "/**").permitAll() 
      .antMatchers("/login").permitAll() 
      .anyRequest().fullyAuthenticated() 
      .and() 
     .httpBasic() 
      .and() 
     .sessionManagement() 
      .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
      .and() 
     .csrf().disable(); 
} 

Kể từ Xuân An 4.2.0 bạn có thể sử dụng sự hỗ trợ tích hợp, xem Spring Security Reference:

19. CORS

Spring Framework cung cấp hỗ trợ lớp học đầu tiên cho CORS. CORS phải được xử lý trước Spring Security vì yêu cầu trước chuyến bay sẽ không chứa bất kỳ cookie nào (ví dụ: JSESSIONID). Nếu yêu cầu không chứa bất kỳ cookie nào và Bảo mật mùa xuân trước tiên, yêu cầu sẽ xác định người dùng không được xác thực (vì không có cookie trong yêu cầu) và từ chối nó.

Cách dễ nhất để đảm bảo rằng CORS được xử lý trước tiên là sử dụng CorsFilter. Người dùng có thể tích hợp các CorsFilter với Xuân An bằng cách cung cấp một CorsConfigurationSource sử dụng như sau:

@EnableWebSecurity 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      // by default uses a Bean by the name of corsConfigurationSource 
      .cors().and() 
      ... 
    } 

    @Bean 
    CorsConfigurationSource corsConfigurationSource() { 
     CorsConfiguration configuration = new CorsConfiguration(); 
     configuration.setAllowedOrigins(Arrays.asList("https://example.com")); 
     configuration.setAllowedMethods(Arrays.asList("GET","POST")); 
     UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 
     source.registerCorsConfiguration("/**", configuration); 
     return source; 
    } 
} 
+0

'.andMatchers (HttpMethod.OPTIONS, "/ **"). allowAll() 'không bao giờ làm việc cho tôi, nó không đưa ra các tiêu đề CORS thích hợp trên' OPTIONS'. Chỉ kỹ thuật CORS được Spring Security chấp thuận mới hoạt động. –

+0

@IndraKP Nếu bạn sử dụng Bảo mật mùa xuân> = 4, thì hãy sử dụng cách khác. Nếu bạn sử dụng Spring Security 3 thì bạn phải nhập đúng lớp 'HttpMethod'. – dur

3

Kể từ Xuân An 4.1, đây là cách thích hợp để làm CORS hỗ trợ Xuân An (còn cần thiết trong mùa xuân Boot 1.4/1.5):

@Configuration 
public class WebConfig extends WebMvcConfigurerAdapter { 

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

và:

@Configuration 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 
    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
//  http.csrf().disable(); 
     http.cors(); 
    } 

    @Bean 
    public CorsConfigurationSource corsConfigurationSource() { 
     final CorsConfiguration configuration = new CorsConfiguration(); 
     configuration.setAllowedOrigins(ImmutableList.of("*")); 
     configuration.setAllowedMethods(ImmutableList.of("HEAD", 
       "GET", "POST", "PUT", "DELETE", "PATCH")); 
     // setAllowCredentials(true) is important, otherwise: 
     // The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. 
     configuration.setAllowCredentials(true); 
     // setAllowedHeaders is important! Without it, OPTIONS preflight request 
     // will fail with 403 Invalid CORS request 
     configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type")); 
     final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 
     source.registerCorsConfiguration("/**", configuration); 
     return source; 
    } 
} 

Do không làm bất cứ dưới đây, đó là một cách sai lầm để cố gắng giải quyết vấn đề:

  • http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
  • web.ignoring().antMatchers(HttpMethod.OPTIONS);

tham khảo: http://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html

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