为 CORS 配置 Spring

Posted

技术标签:

【中文标题】为 CORS 配置 Spring【英文标题】:Configure Spring for CORS 【发布时间】:2019-06-12 20:02:33 【问题描述】:

我正在尝试 以使用 Angular Web UI:

我试过了:

@Configuration
@ComponentScan("org.datalis.admin.config")
public class AppConfig 

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigurer() 
        PropertySourcesPlaceholderConfigurer conf = new PropertySourcesPlaceholderConfigurer();
        conf.setLocation(new ClassPathResource("application.properties"));
        return conf;
    

    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("127.0.0.1");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<CorsFilter>(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    

带有 Angular FE 的 Apache 服务器与 Wildly 服务器在同一台服务器上运行,因此我为源配置了 127.0.0.1。

但我还是明白了:

Access to XMLHttpRequest at 'http://123.123.123.123:8080/api/oauth/token' from origin 'http://123.123.123.123' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
auth:1 Failed to load resource: the server responded with a status of 404 (Not Found)

你知道我该如何解决这个问题吗?

我尝试的第二种方法:

@Configuration
@EnableResourceServer
public class ResourceSecurityConfig extends ResourceServerConfigurerAdapter 

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) 
        resources.resourceId("resource_id").stateless(true);
    

    @Override
    public void configure(HttpSecurity http) throws Exception 
        http.authorizeRequests()
                .antMatchers("/users/**").permitAll()
                .anyRequest().authenticated()
                .and()
        .cors().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
        .anyRequest()
        .fullyAuthenticated()
        .and()
        .httpBasic()
        .and()
        .csrf().disable();
    

    @Bean
    public CorsConfigurationSource corsConfigurationSources() 
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", "x-auth-token"));
        configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    

第二个配置我得到has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status. auth:1 Failed to load resource: the server responded with a status of 404 (Not Found)

实现此结果的最佳方法是什么?

【问题讨论】:

顺便说一句,您可能需要考虑将优先级设置为bean.setOrder(Ordered.HIGHEST_PRECEDENCE) 而不是零。 现在我得到请求的资源上没有“Access-Control-Allow-Origin”标头。 ***.com/a/53863603/10426557 @JonathanJohx 我从源 '123.123.123.123:8080/api/oauth/token' 获得对 XMLHttpRequest 的访问权限 '123.123.123.123' 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:它没有有 HTTP ok 状态。 还有其他建议如何解决这个问题? 【参考方案1】:

尝试将您的 bean 名称更改为 corsConfigurationSource 删除“s”

文档https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#cors

// 默认使用名为 corsConfigurationSource 的 Bean

【讨论】:

【参考方案2】:

您需要在控制器类中添加@CrossOrigin 类级别,如下所示

@CrossOrigin
public class SampleController 
    // Your code goes here

对你的休息控制器类的注释

【讨论】:

【参考方案3】:

这是我的工作 @Configuration 类,用于处理仅在开发环境中使用的 CORS 请求。

@Configuration
//@Profile(PROFILE_DEV)
  public class CorsConfiguration 

  @Bean
  public WebMvcConfigurer corsConfigurer() 
      return new WebMvcConfigurer() 
          @Override
          public void addCorsMappings(CorsRegistry registry) 
              registry.addMapping("/**")
                  .allowedOrigins("*")
                  .allowedHeaders("*")
                  .allowedMethods("*");
          
      ;
  

您还必须配置 Spring Security 以忽略预检请求使用的HttpMethod.OPTIONS(作为您提到的例外)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter 
  //...
    @Override
    public void configure(WebSecurity web) throws Exception 
      web.ignoring()
            //others if you need
            .antMatchers(HttpMethod.OPTIONS, "/**");

    

    @Override
    public void configure(HttpSecurity http) throws Exception 
        http
            .csrf()
            .disable()
            .exceptionHandling()
            .and()
            .headers()
            .frameOptions()
            .disable()
            .and()
            .authorizeRequests()
            .antMatchers("/api/register").permitAll()
            .antMatchers("/api/activate").permitAll()
            .antMatchers("/api/authenticate").permitAll()
            .antMatchers("/api/**").authenticated();
    


因为当您使用 cors 时,您有 Simple Request 和 Preflighted Request 触发 HttpMethod.OPTIONS

【讨论】:

我也使用 Spring 安全性。这适用于 Spring Security 吗? 使用 spring security OPTIONS 配置更新答案 我尝试将您的建议与@Angelo Immediata 的建议结合起来,但我仍然遇到同样的问题。任何其他想法如何解决它? 我的解决方案不需要添加其他东西。尝试按照我的解释保留代码,只要确保 @Configuration 类已正确加载。告诉我你是否还有异常 我只测试了你的代码。不幸的是,这个问题没有得到解决。【参考方案4】:

我建议您使用 WebMvcConfigurer,并在 addCorsMappings 方法中设置 CORS 配置。

类似的东西

@Configuration
public class WebConfig implements WebMvcConfigurer 
    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**")
            .allowedOrigins("http://localhost:9798")
            .allowedMethods("POST", "GET")
            //.allowedHeaders("header1", "header2", "header3")
            //.exposedHeaders("header1", "header2")
            .allowCredentials(true).maxAge(3600);
    

这里有一个完整功能的 Spring with CORS 项目的链接,只需下载并运行它。

https://github.com/reos79/spring-cors

它有一个 html 页面 (person.html) 这个页面什么都不做,只是调用端口 (9797) 上的服务。所以你需要加载这个项目两次,一次在端口 9797 上加载服务,另一个在端口 (9798) 上。然后在浏览器上调用服务器 localhost:9798 上的页面人员,它将调用 localhost:9797 上的服务,在 application.properties 文件中我配置了端口。

【讨论】:

你知道我需要在 Apache 和 Angular 中添加一些配置吗? 这是使用您的配置的 Wildfly 配置文件:pastebin.com/TzXPsNwt 您是否删除了 Bean public CorsConfigurationSource corsConfigurationSources() ?和 Bean public FilterRegistrationBean corsFilter() ? 是的,我做到了。但我稍后会用干净的设置再试一次。 这是第二次尝试的结果:pastebin.com/q5eRqSz8【参考方案5】:

您需要告诉 Spring Security 使用您创建的 CORS 配置。

在我的项目中,我以这种方式配置了Spring Security

@Override
protected void configure(HttpSecurity http) throws Exception

    http
        .authorizeRequests()
        .antMatchers("/rest/protected/**")
        .authenticated()
     //Other spring sec configruation and then:
    .and()
        .cors()
        .configurationSource(corsConfigurationSource())


corsConfigurationSource() 在哪里:

@Bean
    CorsConfigurationSource corsConfigurationSource() 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        boolean abilitaCors = new Boolean(env.getProperty("templating.oauth.enable.cors"));
        if( abilitaCors )
        
            if( logger.isWarnEnabled() )
            
                logger.warn("CORS ABILITATI! Si assume ambiente di sviluppo");
            
            CorsConfiguration configuration = new CorsConfiguration();
            configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200","http://localhost:8080", "http://localhost:8180"));
            configuration.setAllowedMethods(Arrays.asList(  RequestMethod.GET.name(),
                    RequestMethod.POST.name(), 
                    RequestMethod.OPTIONS.name(), 
                    RequestMethod.DELETE.name(),
                    RequestMethod.PUT.name()));
            configuration.setExposedHeaders(Arrays.asList("x-auth-token", "x-requested-with", "x-xsrf-token"));
            configuration.setAllowedHeaders(Arrays.asList("X-Auth-Token","x-auth-token", "x-requested-with", "x-xsrf-token"));
            source.registerCorsConfiguration("/**", configuration);
        
        return source;
    

希望对你有用

安杰洛

【讨论】:

我又可以在'http://123.123.123.123:8080/api/oauth/token' from origin 'http://123.123.123.123' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status. 获得对 XMLHttpRequest 的访问权限@还有其他想法吗? 据我所知,我理解:您必须通过 AJAX 配置 IP 地址为 123.123.123.123 的 cors 源。您是否还添加了IP地址?您是否通过添加正确的 IP 地址修改了 CorsConfigurationSource?放入 TRACE spring 安全日志 在您的logback.xml 文件中添加一个类似&lt;logger name="org.springframework.security" level="TRACE"&gt;&lt;/logger&gt; 的spring 记录器 好的,我稍后再试试。您在我的 Spring-boot/Spring Security 配置中看到问题了吗? 我不是 Spring Boot 专家,但在我看来一切正常,除了 cors 配置被注释了【参考方案6】:

您允许的来源是 127.0.0.1,但您的客户端具有 ip 123.123.123.123。尝试改变这一点:

config.addAllowedOrigin("127.0.0.1");

到这里:

config.addAllowedOrigin("123.123.123.123");

【讨论】:

嗨拉斐尔!欢迎来到 ***。我编辑了您的帖子以格式化代码 - 以供将来参考,代码块通过用四个空格缩进来格式化。 您可以尝试在您的客户端上添加标题“with credentials: true”。您可以在 Angular 上在 http 客户端上添加拦截器。见***.com/questions/38615205/…

以上是关于为 CORS 配置 Spring的主要内容,如果未能解决你的问题,请参考以下文章

SpringSpring MVC原理及配置详解

SpringSpring MVC原理及配置详解

SpringSpring MVC原理及配置详解

Springspring模块和spring portfolio

Springspring模块和spring portfolio

SpringSpring MVCMyBatis