CORS 问题 - 请求的资源上不存在“Access-Control-Allow-Origin"标头 [英] CORS issue - No 'Access-Control-Allow-Origin' header is present on the requested resource

查看:59
本文介绍了CORS 问题 - 请求的资源上不存在“Access-Control-Allow-Origin"标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have created two web applications - client and service apps.
The interaction between client and service apps goes fine when they are deployed in same Tomcat instance.
But when the apps are deployed into seperate Tomcat instances (different machines), I get the below error when request to sent service app.

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.

My Client application uses JQuery, HTML5 and Bootstrap.

对服务进行 AJAX 调用,如下所示:

AJAX call is made to service as shown below:

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.

My service application uses Spring MVC, Spring Data JPA and Spring Security.

我已经包含了 CorsConfiguration 类,如下所示:

I have included CorsConfiguration class as shown below:

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 依赖项:

Spring Security dependencies:

 <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 服务器进行部署.

I am using Apache Tomcat server for deployment.

推荐答案

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

CORS' preflight request uses HTTP OPTIONS without credentials, see Cross-Origin Resource Sharing:

否则,请提出预检请求.使用引用源作为覆盖引用源,使用手动重定向标志和阻止 cookie 标志集,使用方法 OPTIONS 和以下附加约束,从源源获取请求 URL:

Otherwise, make a preflight request. Fetch the request URL from origin source origin using referrer source as override referrer source with the manual redirect flag and the block cookies flag set, using the method OPTIONS, and with the following additional constraints:

  • 包含一个 Access-Control-Request-Method 标头,其中包含请求方法的标头字段值(即使这是一个简单的方法).
  • 如果作者请求标头不为空,则包含一个 Access-Control-Request-Headers 标头,标头字段值为逗号分隔的标头字段名称列表,按字典顺序来自作者请求标头,每个标头都转换为 ASCII 小写(甚至当一个或多个是简单标题时).
  • 排除作者请求标头.
  • 排除用户凭据.
  • 排除请求实体正文.

您必须允许匿名访问 HTTP OPTIONS.

You have to allow anonymous access for HTTP OPTIONS.

Spring 安全 3

您修改(和简化)的代码:

Your modified (and simplified) code:

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

您仍然需要 CORS 配置(可能还有一些附加值):

You still need your CORS configuration (probably with some additional values):

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

Spring 安全 4

从 Spring Security 4.2.0 开始,您可以使用内置支持,请参阅 Spring 安全参考:

Since Spring Security 4.2.0 you can use the built-in support, see Spring Security Reference:

19.CORS

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

Spring Framework provides first class support for CORS. CORS must be processed before Spring Security because the pre-flight request will not contain any cookies (i.e. the JSESSIONID). If the request does not contain any cookies and Spring Security is first, the request will determine the user is not authenticated (since there are no cookies in the request) and reject it.

确保首先处理 CORS 的最简单方法是使用 CorsFilter.用户可以通过使用以下内容提供 CorsConfigurationSourceCorsFilter 与 Spring Security 集成:

The easiest way to ensure that CORS is handled first is to use the CorsFilter. Users can integrate the CorsFilter with Spring Security by providing a CorsConfigurationSource using the following:

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

这篇关于CORS 问题 - 请求的资源上不存在“Access-Control-Allow-Origin"标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆