如何在 Springfox Swagger 提供的 Swagger /v2/api-docs 中启用 CORS 标头?

问题描述 投票:0回答:3

我的项目中有以下文件:

@Configuration
@Order(Ordered.LOWEST_PRECEDENCE)
public class SwaggerConfig {

    @Bean
    public Docket apiSwagger2Documentation() { .... }
}

在Application.java中有:

@SpringBootApplication
@ComponentScan(basePackages = { ... })
@EnableSwagger2
public class Application {
    ...
}

Swagger JSON 在

/v2/api-docs
下可用,效果很好。

我想做的是为该端点启用 CORS 标头。

对于我自己的控制器,我已将

@CrossOrigin
添加到控制器类中,然后这些 API 具有 CORS 标头,效果很好。但对于 Swagger JSON URL,我自己还没有编写控制器,所以我无法使用该注释。

我在

SwaggerConfig
中添加了以下方法,如Spring Framework中的CORS支持中的“全局CORS配置”中所述。

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        System.out.println("*** corsConfigurer called");
        return new WebMvcConfigurerAdapter() {
            @Override public void addCorsMappings(CorsRegistry registry) {
                System.out.println("*** addCorsMappings called");
                registry.addMapping("/v2/api-docs");
            }
        };
    }

两个打印语句都被打印,因此正在调用该方法。但是当我用curl调用URL时:

curl -H "Origin: foo.com"  \
   -H "Access-Control-Request-Method: GET"   \
   -X OPTIONS \ 
   --verbose  \
   http://localhost:9274/v2/api-docs

CORS 标头不在响应中。 (与我自己的控制器方法相反,用

@CrossOrigin
注释,其中响应确实具有 CORS 标头。)

我正在使用 springfox-swagger2 版本 2.7.0 和 spring-boot-starter-web 1.5.2。

如何在 Swagger JSON API 端点上启用 CORS 标头?

spring spring-mvc spring-boot springfox
3个回答
24
投票

我认为你需要一个通用的 Web 过滤器,而不是 Web Mvc 配置。

@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    // Allow anyone and anything access. Probably ok for Swagger spec
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");

    source.registerCorsConfiguration("/v2/api-docs", config);
    return new CorsFilter(source);
}

4
投票

感谢@Barath 的回答。解决方案是忽略 Spring 文档,该代码似乎默默地不起作用。

(遗憾的是,Spring 的东西在工作时相当先进,例如,预检请求的“Access-Control-Allow-Headers”响应标头是根据 Java API 方法实际提供的标头设置的.)

忽略 Spring 的 CORS 实现并自行实现。我已将对我有用的代码放在这里:

@Component
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
    throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "Foo, Bar, Baz");
        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) {}

    @Override
    public void destroy() {}
}

请记住将您在任何 REST 方法中使用的任何

@RequestHeader
添加到
Access-Control-Allow-Headers
响应标头


0
投票

为了详细说明@Adrian Smith 2017年8月15日9:17的回答,我的解决方案如下,因为它还需要

Access-Control-Allow-Headers: content-type
才能使飞行前请求通过。

@Component
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        if(iteratorToFiniteStream(request.getHeaderNames().asIterator()).count()  h.equalsIgnoreCase("access-control-request-method"))
            .findFirst().ifPresent(h -> response.setHeader("Access-Control-Allow-Methods", request.getHeader(h)));
        }
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Headers", "content-type");
        response.setHeader("Access-Control-Max-Age", "0"); // After testing, better set this to 3600 or so
        response.setHeader("Allow", "GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH");
        chain.doFilter(req, res);
    }
    
    static (T) Stream(T) iteratorToFiniteStream(final Iterator(T) iterator) {
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }
}

将 (T) 替换为 < T >!也就是说,我质疑 CORS 的有用性,其中 Web 服务器友好地询问 Web 客户端要使用(不)使用哪个端点。

© www.soinside.com 2019 - 2024. All rights reserved.