Skip to content

修复 CorsFilter Bean 有时不起作用的问题

🏷️ Spring Boot

通过代码配置 CorsFilter bean 时,有时仍然会报跨域的问题,怀疑和 Filter 的执行顺序有关。另外有时部分接口可以,部分接口不可以,因为 filter 是全局的,怀疑可能跟浏览器的配置有关。还有就是有时谷歌浏览器的隐私模式没有跨域问题,当时相同的代码在非隐私模式就会报跨域错误。

根据 这篇博客 修改为使用自定义 CorsFilter 并指定 @Order 为最优先,即可解决这个问题。具体的代码见 附 2. AjaxCorsFilter

附 1. GlobalCorsConfig

java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1.添加 CORS 配置信息
        CorsConfiguration config = new CorsConfiguration();
        //放行哪些原始域
        config.addAllowedOrigin("*");
        //是否发送 Cookie 信息
        config.setAllowCredentials(true);
        //放行哪些原始域 (请求方式)
        config.addAllowedMethod("*");
        //放行哪些原始域 (头部信息)
        config.addAllowedHeader("*");
        //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
        config.addExposedHeader("Content-Type");
        config.addExposedHeader("X-Requested-With");
        config.addExposedHeader("accept");
        config.addExposedHeader("Origin");
        config.addExposedHeader("Access-Control-Request-Method");
        config.addExposedHeader("Access-Control-Request-Headers");

        //2.添加映射路径
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);

        //3.返回新的 CorsFilter.
        return new CorsFilter(configSource);
    }
}

附 2. AjaxCorsFilter

java
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Arrays;
import java.util.List;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@Slf4j
public class AjaxCorsFilter extends CorsFilter {
    /**
     * Constructor accepting a {@link CorsConfigurationSource} used by the filter
     * to find the {@link CorsConfiguration} to use for each incoming request.
     *
     * @see UrlBasedCorsConfigurationSource
     */
    public AjaxCorsFilter() {
        super(configurationSource());
    }

    private static UrlBasedCorsConfigurationSource configurationSource() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        List<String> allowedHeaders = Arrays.asList("*");
        List<String> exposedHeaders = Arrays.asList("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers");
        List<String> allowedMethods = Arrays.asList("*");
        List<String> allowedOrigins = Arrays.asList("*");
        corsConfig.setAllowedHeaders(allowedHeaders);
        corsConfig.setAllowedMethods(allowedMethods);
        corsConfig.setAllowedOrigins(allowedOrigins);
        corsConfig.setExposedHeaders(exposedHeaders);
        corsConfig.setMaxAge(36000L);
        corsConfig.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig);
        return source;
    }
}