非默认端口上的反向代理背后的 Spring Boot Cors

Posted

技术标签:

【中文标题】非默认端口上的反向代理背后的 Spring Boot Cors【英文标题】:Spring Boot Cors behind reverse-proxy on non-default port 【发布时间】:2018-04-02 14:04:42 【问题描述】:

我的应用程序有一个使用 Spring Boot 构建的后端,以及一个使用 Angular 构建并由 nginx 提供服务的前端 Web 应用程序。 Nginx 配置为将到 /api/ 的请求反向代理到后端:

location /api/ 
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass http://back:8080;

如果 nginx 在默认端口 (80) 上运行,我可以在 http://myserver/ 访问我的应用程序而不会出现问题。对http://myserver/api/some/REST/resource 的 XHR 调用完美运行。

如果我将 nginx 更改为监听其他端口(随机:9043),那么所有 XHR 调用都会失败,并出现错误“无效的 CORS 请求”。这是出乎意料的,因为只有我的前端应用程序在调用 API,并且由于反向代理,此 API 与 javascript 文件在同一主机上提供。

为了让它发挥作用,我需要将它添加到我的 Spring 应用程序中:

@Configuration
public class CorsConfig 

    @Value("$url.base:''")
    private String urlBase;

    @Value("$cors.allowed.origins:[]")
    private String[] allowedOrigins;

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

然后在我的配置中将cors.allowed.origins 设置为http://myserver:9043/

这行得通,但如果我要这样做就不实用了:

使主机名和/或端口动态化(端口从 CI 构建期间的分支名称派生,然后将容器部署到 Rancher 集群) 将 nginx 隐藏在负载平衡器后面(= 另一个级别的反向代理)

是否有解决方案通过执行以下任何操作来解决此问题:

验证 CORS 请求时是否让 spring boot 忽略端口号? 让 nginx 调整代理请求的内容,以便 Spring 的 CORS 验证成功?

编辑:更多细节和示例:

服务是 dockerized :

前端:nginx 监听容器内的 80 端口,docker 将其作为端口 9043 暴露在主机上 Backend : spring boot 监听 8080。该端口不是 Docker 导出的,所以只能从前端容器访问,该容器有一个到后端容器的链接。

仅当前端在 80 端口上暴露给外界时才有效...

【问题讨论】:

即使主机相同,如您所见,如果前端和后端位于不同的端口上,您将需要 CORS 标头。 您是否尝试使用属性“server.address”映射您的端点?如果你定义了你的端点,我没记错的话,这将被 cors 使用,你将拥有它的端口。 @lbndev ¿你解决了这个问题吗?我被一个类似的问题困住了(它只发生在 Chrome 上,而不是 Firefox,很奇怪) @PabloLozano : 否 :( 最终,我在基础设施上解决了这个问题(使用 traefik LB + 通配符 DNS),所以我总是使用端口 80(或 443)。但问题仍然有效并打开。 @lbndev 我通过添加到代理配置proxy_set_header Origin ""; 解决了这个问题。似乎这个标头是由 Spring 检查的(标头不是由 Firefox 添加的,这就是它起作用的原因) 【参考方案1】:

在反向请求中添加两个http头:

X-Forwarded-Proto

X-转发端口

indecate 原始 proto 和端口(匹配原始请求)。

查看更多:https://moi.vonos.net/java/spring-forward/

【讨论】:

实际上,X-Forwarded-Host 也可能是个问题。我接受这个答案,因为当反向代理也执行 SSL 终止时,它为端口和方案(原型)提供了有效的解决方案。非常感谢 ! :)

以上是关于非默认端口上的反向代理背后的 Spring Boot Cors的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot - Apache 反向代理背后的 Spring 安全性

NGINX 反向代理背后的 Spring Boot API REST

Apache反向代理背后的Keycloak

nginx 80端口代理无效 非80可用

公共反向代理背后的 WCF Webservice

为Docker创建自动化nginx反向代理