(注意:此行为已在 keycloak tomcat Valve 6.0.1 中重现)
[已更新以包含解决方案]
经过大量实验,问题似乎是这样的:
Keycloak 向 CORS 预检 (OPTIONS) 请求发回 401 响应。无论您向预检添加什么标头,错误状态代码(即除了 200 系列响应之外的任何内容)都将被视为 CORS 失败。
解决办法:
1) 扩展 Keycloak-valve 的 CORS 支持以响应 204 到 OPTIONS,可能通过添加如下所示的代码。如果你想检查一下,弄清楚它迷宫般的架构,然后提交 PR,那就太好了。否则,
2) 禁用 keycloak 的 CORS 支持并在您的配置中添加一个 CORS 阀。
我通过设置“enable_cors: false”(或简单地删除条目)禁用了仅承载服务器中的 CORS 支持。然后我创建了一个小的 CORS 支持阀来发送 Access-Control-Allow- 标头。因为这是一个不记名令牌系统,所以允许“*”是相当安全的。 (此外,如果您允许来源“*”,现代浏览器将不会发送凭据。)
整个 CORS 支持阀大致如下:
public void invoke(Request rqst, Response rsp) throws ...
{
HttpServletResponse response = rsp.getResponse();
HttpServletRequest request = rqst.getRequest();
if (null != request.getHeader("origin")) {
response.setHeader("Access-Control-Allow-Origin", "*");
String method = request.getMethod();
if (method.equalsIgnoreCase("options")) { // preflight?
rsp.reset();
response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
response.setHeader("Access-Control-Max-Age", "10");
response.setHeader("Access-Control-Allow-Headers", "Origin,Accept,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Your-Header-Here");
rsp.setStatus(204);
return;
}
}
getNext().invoke(rqst, rsp);
}
但您可能想为您的应用程序编写一个功能更全面的阀门。
添加后,CORS preflight 返回 204,然后请求者正确接收到 401/403 响应。
分析
Keycloak 阀仅在与 Keycloak 身份验证服务器签入后发送 CORS 标头。这意味着承载令牌服务器端应用程序的任何联网、配置或令牌验证失败都会导致没有任何 Access-Control-Allow 标头的错误响应,因此没有任何错误详细信息可用。
Keycloak tomcat 阀确实为几乎所有故障提供详细的故障信息。对于 401 错误,它位于 WWW-Authenticate 响应标头中,与大多数标头一样,在 CORS 失败的情况下禁止使用该标头。但是,它会将此 401 错误返回给 OPTIONS 请求,即 CORS 预检,它将其隐藏在客户端代码中。由于任何配置错误(auth-server-url 的端口错误,或领域拼写错误)也会触发 CORS 失败,因此您的应用永远不会看到标头。
该错误在某些浏览器的网络调试窗格中可见,但对 Javascript 不可见。