keycloak + spring 适配器 +spring security 反向代理重定向到root

Posted

技术标签:

【中文标题】keycloak + spring 适配器 +spring security 反向代理重定向到root【英文标题】:keycloak + spring adapter +spring security reverse proxy redirecting to root 【发布时间】:2018-06-22 05:04:40 【问题描述】:

我们一直在使用 Apache 2.2 反向代理让多个应用程序在同一个 VM 上运行。在我们添加 Keycloak 适配器 3.4.0.Final + spring security 1.5.9.RELEASE 之前,一切正常。

这就是它的工作原理:

VM1 应用程序1 应用程序2

虚拟机2 钥匙斗篷

同一网络上的笔记本电脑 浏览器 app1 - 用于开发目的

场景: 1)笔记本电脑之间一切正常 - 带有应用程序的VM2。 2)浏览器笔记本电脑-VM1-VM2之间一切正常,当没有反向代理时(所以直接访问应用程序端口)。 3) 反向代理到位时的问题。浏览器笔记本电脑 - VM1(带有 mod_prox 的 Apache) - VM2

我遵循了文档中的所有建议:

http://www.keycloak.org/docs/1.9/server_installation_guide/topics/clustering/load-balancer.html

http://www.keycloak.org/docs/latest/server_installation/index.html#_setting-up-a-load-balancer-or-proxy

这是我以前的规则:

LoadModule proxy_module modules/mod_proxy.so
ProxyRequests On

<Proxy *>
    Order deny,allow
    Allow from all
</Proxy>

ProxyPassMatch    ^/MyAPP/(.+) http://localhost:8585/MyAPP/$1
ProxyPassReverse  ^/MyAPP/(.+) http://localhost:8585/MyAPP/$1
ProxyPreserveHost On

观察到: GET VM1/MyAPP/index.html -> 使用正确的重定向 url 重定向到 VM2 keycloak GET VM1/MyAPP/index.html?State=xxxx -> 重定向到 / GET / -> root 上没有任何东西,所以它会在这里结束

第一个变化: 我已经看到造成这种情况的原因是 keycloak 成功处理程序将我重定向到 root。 所以我将其更改为将其重定向到同一页面:

public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean( KeycloakAuthenticationProcessingFilter filter)
    FilterRegistrationBean registrationBean = new 
    FilterRegistrationBean(filter);
    successHandler = new AuthenticationSuccessHandler();
    successHandler.setDefaultTargetUrl("/MyAPP/index.html");
    filter.setAuthenticationSuccessHandler(successHandler);

观察到:

GET VM1/MyAPP/index.html -> redirected to VM2 keycloak with the right redirect url
GET VM1/MyAPP/index.html?State=xxxx -> redirected to /MyAPP/index.html
GET VM1/MyAPP/index.html?State=xxxx -> redirected to /MyAPP/index.html
GET VM1/MyAPP/index.html?State=xxxx -> redirected to /MyAPP/index.html
GET VM1/MyAPP/index.html?State=xxxx -> redirected to /MyAPP/index.html
GET VM1/MyAPP/index.html?State=xxxx -> redirected to /MyAPP/index.html
GET VM1/MyAPP/index.html?State=xxxx -> redirected to /MyAPP/index.html
....

无限循环。我还注意到应用程序每次都在进行身份验证。 可疑的。

所以我开始怀疑是 apache 导致了问题,并决定尝试使用不同的代理: 代理服务器。 它因同样的问题而失败。 但我被重定向到 /sso/login intead

所以下一步是调试不同的请求:代理与非代理

VM1/MyAPP vs VM1:8585/MyAPP

所以我发现每次请求具有授权标头时它都会对请求进行身份验证。这只发生在代理版本中。

因此,使用 apache 2.2,您无法删除标头。刚刚添加到 2.4 所以再次使用haproxy,并以相同的方式尝试强制删除授权标头。它几乎奏效了。我遇到了一些问题,请求方法是 1 而不是 GET。奇怪...

长话短说现在很明显,基本身份验证是问题所在。

如何解决这个问题?

更新:

我现在的问题是: 如何更改 KeycloakAuthenticationEntryPoint loginUri 以在配置中包含我的反向代理的子上下文? - 在 root 上拥有反向代理“sso/login”不会让我在同一服务器上拥有超过 1 个 keycloak 应用程序。

【问题讨论】:

【参考方案1】:

我是如何解决这个问题的:

1) 所以第一步是禁用干扰 keycloak 授权过程或至少干扰 spring 安全性的 apache 上的基本身份验证。

在这之后我开始注意到我总是被重定向到根目录下的 /sso/login。

2) 为了解决这个问题,我添加了一个新的代理通过规则来将 sso/login 请求重定向到我的服务器。

ProxyPassMatch ^/sso/login(.*) http://localhost:8585/sso/login$1

ProxyPassReverse ^/sso/login(.*) http://localhost:8585/sso/login$1

在此之后,我仍然被重定向到 /sso/login 或只是到根目录。 尝试使用隐身模式后,我发现它确实有效。 尝试了不同的浏览器,效果也不错。

3) 一些旧会话状态仍在我的浏览器上,因此清除所有 cookie 关闭所有浏览器选项卡并重新启动 chrome 并开始工作。

4) 要点 2 有一个很大的缺陷。它不允许您在同一服务器中拥有多个 keycloak 适配器应用程序。为了改变弹簧侧的行为,我用两个过程来解决它。 - 第一个是在keycloakAuthenticationEntryPoint上重新设置登录uri

    @Autowired
    AdapterDeploymentContext adapterDeploymentContext;
    private static final String OAUTH_LOGIN_URL = "/sso/login";
     @Override
    protected void configure(HttpSecurity http) throws Exception
       KeycloakAuthenticationEntryPoint keycloakAuthenticationEntryPoint =
       new KeycloakAuthenticationEntryPoint(adapterDeploymentContext);
       keycloakAuthenticationEntryPoint.setLoginUri(realSubContext + OAUTH_LOGIN_URL);
       ...
    

第二个是为sso登录添加重定向重写规则 钥匙斗篷: 重定向重写规则: "^/sso/login(.*)$": "/MYSUBCONTEXT/sso/login$1"

【讨论】:

以上是关于keycloak + spring 适配器 +spring security 反向代理重定向到root的主要内容,如果未能解决你的问题,请参考以下文章

生成 SP 元数据时出现意外的堆栈跟踪表单 Spring-Security-SAML?

使用 Spring Security Saml 和 SP 应用程序的无状态会话

如何使用 SP 密钥库 spring saml 中的证书

在反向代理后面使用 SP 时出现 Spring saml 问题

Spring saml,第二个本地 SP - 实体别名和上下文提供者

Spring saml - 在SP上启动登录时如何记住请求参数,并在IdP响应后处理它们