一尘不染

CORS问题-所请求的资源上没有“ Access-Control-Allow-Origin”标头

spring

我已经创建了两个Web应用程序-客户端和服务应用程序。
当客户端和服务应用程序部署在同一Tomcat实例中时,它们之间的交互就很好。
但是,当将应用程序部署到单独的Tomcat实例(不同的计算机)中时,请求发送服务应用程序时出现以下错误。

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

我的客户端应用程序使用JQuery,HTML5和Bootstrap。

如下所示进行AJAX呼叫服务:

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

我的服务应用程序使用Spring MVC,Spring Data JPA和Spring Security。

我包含了CorsConfiguration如下所示的类:

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

Spring Security依赖项:

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

我正在使用Apache Tomcat服务器进行部署。


阅读 1040

收藏
2020-04-11

共1个答案

一尘不染

CORS的预检请求使用OPTIONS不带凭据的HTTP ,请参阅跨域资源共享:

否则,请发出预检请求。使用方法OPTIONS和以下附加约束,使用引荐来源来源作为覆盖引荐来源,并设置了手动重定向标志和块cookie标志,从起源来源起点获取请求URL:

  • 包括一个Access-Control-Request-Method标头,并将请求方法作为标头字段值(即使是简单方法也是如此)。
  • 如果作者请求标头不为空,则包含一个Access-Control-Request-Headers标头,并以字母顺序将按字母顺序排列的作者请求标头中的标头字段名的列表以逗号分隔,作为标头字段值,每个都转换为ASCII小写(即使是更多是一个简单的标题)。
  • 排除作者请求标头。
  • 排除用户凭据。
  • 排除请求实体主体。

你必须允许HTTP匿名访问OPTIONS。

你修改(简化)的代码:

@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();
}

从Spring Security 4.2.0开始,你可以使用内置支持,请参阅Spring Security Reference:

  1. CORS

Spring Framework为CORS提供了一流的支持。必须在Spring Security之前处理CORS,因为飞行前请求将不包含任何cookie(即JSESSIONID)。如果请求不包含任何cookie,并且首先使用Spring Security,则该请求将确定用户未通过身份验证(因为请求中没有cookie),并拒绝该用户。

确保首先处理CORS的最简单方法是使用CorsFilter。用户可以CorsFilter通过CorsConfigurationSource使用以下命令将集成到Spring Security中:

@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;
  }
}
2020-04-11