我们应用程序的后端 (API) 建立在 Grails 5.1.1 之上,并且已经在 DiginalOcean 上运行了好几年。我们现在正在尝试将基础架构迁移到 Kubernetes(也在 DO 上)。对于入口控制器,我们使用了 Ambassador Edge Stack(出于各种原因)。
现在,整个集群都已启动并运行,只是我们遇到了 CORS 问题。
注意:通过常规的 LoadBalancer(甚至是相同的图像),完全相同的代码库在 DO 上运行没有问题。
当我们将 API 切换到 Kubernetes 集群时,我们会收到缺少 CORS 标头的错误。
在细节之前,有一点历史......
起初,OPTIONS
请求被拒绝,因为显然 spring-security 拒绝了这些请求。出于某种原因,我们只有在切换到 Kubernetes 时才会遇到这个问题。
我们通过添加另一个过滤器来解决这个问题(拦截器不适用于这种情况,因为它们在安全过滤器之后执行)......
铜过滤器
class CorsFilter extends OncePerRequestFilter {
private allowedOrigins = ["http://localhost:4200",
"https://localhost:4200",
"https://app.priz.guru"]
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain)
throws ServletException, IOException {
String origin = req.getHeader('Origin')
if (allowedOrigins.contains(origin)) {
resp.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
resp.addHeader("Access-Control-Max-Age", "3600")
// resp.addHeader("Access-Control-Allow-Credentials", "true")
resp.addHeader("Access-Control-Allow-Origin", origin)
resp.addHeader("Access-Control-Expose-Headers", "*")
}
if (req.getMethod() == "OPTIONS") {
resp.status = 200
} else {
chain.doFilter(req, resp)
}
}
}
添加到resource.groovy
:
optionsCorsFilter(CorsFilter)
并注册BootStrap.groovy
:
SpringSecurityUtils.clientRegisterFilter(
"optionsCorsFilter",
SecurityFilterPosition.FIRST.order - 1
)
之后,OPTIONS
请求开始按预期工作。顺便说一句,内置的 cors 过滤器仍然处于启用状态。我们可以在这一点上从技术上删除它。
一旦解决了这个问题,我们现在将面临下一个挑战。实际的 API 调用不返回 CORS 标头。
更多细节
就目前的环境而言。 带有托管 LoadBalancer 的 DO 上的 Docker 液滴。
如您所见,CORS 标头都适用于两者。一切都很幸福。
在 Kubernetes 上与大使 字面意思是相同的 docker 镜像。
大使地图:
---
apiVersion: getambassador.io/v2
kind: Mapping
metadata:
name: priz-api
namespace: ambassador
spec:
prefix: /
host: api.priz.guru
service: priz-api.backend
cors:
origins:
- https://app.priz.guru
methods: GET, POST, PUT, PATCH, OPTIONS, DELETE
headers: "*"
# credentials: true
exposed_headers: "*"
max_age: "86400"
注意:即使我完全删除cors
配置,我仍然面临同样的问题。