keycloak + spring 适配器 +spring 安全反向代理重定向到 root
keycloak + spring adapter +spring security reverse proxy redirecting to root
我们一直在使用 Apache 2.2 反向代理在同一个虚拟机上运行多个应用程序 运行。在我们添加 Keycloak adapter 3.4.0.Final + spring security 1.5.9.RELEASE[=66= 之前一切正常].
这就是它的工作原理:
VM1
应用程序1
app2
VM2
钥匙斗篷
同一网络上的笔记本电脑
浏览器
app1 - 用于开发目的
场景:
1) 笔记本电脑 - VM2 与应用程序之间一切正常。
2)当没有反向代理(因此直接访问应用程序端口)时,浏览器笔记本电脑 - VM1 - VM2 之间一切正常。
3)反向代理到位时出现问题。浏览器笔记本电脑 - VM1(Apache mod_prox) - VM2
我遵循了文档中的所有建议:
http://www.keycloak.org/docs/1.9/server_installation_guide/topics/clustering/load-balancer.html
这些是我之前的规则:
LoadModule proxy_module modules/mod_proxy.so
ProxyRequests On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPassMatch ^/MyAPP/(.+) http://localhost:8585/MyAPP/
ProxyPassReverse ^/MyAPP/(.+) http://localhost:8585/MyAPP/
ProxyPreserveHost On
观察到:
GET VM1/MyAPP/index.html -> 使用正确的重定向 url 重定向到 VM2 keycloak
GET VM1/MyAPP/index.html?State=xxxx -> 重定向到 /
GET / -> root 上没有任何内容,所以它会在这里结束
第一个变化:
我已经看到这是一个将我重定向到 root 的 keycloak 成功处理程序的原因。
所以我将其更改为将其重定向到与此相同的页面:
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
....
Infinite loop.I 还注意到该应用程序每次都在进行身份验证。
可疑的。
所以我开始怀疑是 apache 导致了问题,并决定尝试使用不同的代理:
haproxy。
它因同样的问题而失败。
但是我被重定向到 /sso/login intead
所以下一步是调试不同的请求:代理与非代理
VM1/MyAPP vs VM1:8585/MyAPP
所以我发现每次请求获得授权时它都会对请求进行身份验证 header.This 仅在代理版本中发生。
因此,对于 apache 2.2,您无法删除 headers。那是刚刚在 2.4 上添加的
于是又haproxy了,同样的方法试了强制取消授权header。它几乎奏效了。我遇到了一些问题,请求方法是 1 而不是 GET。奇...
长话短说现在很明显基本身份验证是问题所在。
如何解决这个问题?
更新:
我现在的问题是:
如何更改 KeycloakAuthenticationEntryPoint loginUri 以在配置中包含我的反向代理的子上下文?
- 在 root 上有一个反向代理 "sso/login" 不会让我在同一台服务器上有超过 1 个 keycloak 应用程序。
我是怎么解决问题的:
1) 因此,第一步是在干扰 keycloak 授权过程或至少 spring 安全性的 apache 上禁用基本身份验证。
此后我开始注意到我总是被重定向到 root 上的 /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 适配器应用程序。为了改变 spring 端的行为,我用两个过程解决了它。
- 第一个是在 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"
我们一直在使用 Apache 2.2 反向代理在同一个虚拟机上运行多个应用程序 运行。在我们添加 Keycloak adapter 3.4.0.Final + spring security 1.5.9.RELEASE[=66= 之前一切正常].
这就是它的工作原理:
VM1 应用程序1 app2
VM2 钥匙斗篷
同一网络上的笔记本电脑 浏览器 app1 - 用于开发目的
场景: 1) 笔记本电脑 - VM2 与应用程序之间一切正常。 2)当没有反向代理(因此直接访问应用程序端口)时,浏览器笔记本电脑 - VM1 - VM2 之间一切正常。 3)反向代理到位时出现问题。浏览器笔记本电脑 - VM1(Apache mod_prox) - VM2
我遵循了文档中的所有建议:
http://www.keycloak.org/docs/1.9/server_installation_guide/topics/clustering/load-balancer.html
这些是我之前的规则:
LoadModule proxy_module modules/mod_proxy.so
ProxyRequests On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPassMatch ^/MyAPP/(.+) http://localhost:8585/MyAPP/
ProxyPassReverse ^/MyAPP/(.+) http://localhost:8585/MyAPP/
ProxyPreserveHost On
观察到: GET VM1/MyAPP/index.html -> 使用正确的重定向 url 重定向到 VM2 keycloak GET VM1/MyAPP/index.html?State=xxxx -> 重定向到 / GET / -> root 上没有任何内容,所以它会在这里结束
第一个变化: 我已经看到这是一个将我重定向到 root 的 keycloak 成功处理程序的原因。 所以我将其更改为将其重定向到与此相同的页面:
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
....
Infinite loop.I 还注意到该应用程序每次都在进行身份验证。 可疑的。
所以我开始怀疑是 apache 导致了问题,并决定尝试使用不同的代理: haproxy。 它因同样的问题而失败。 但是我被重定向到 /sso/login intead
所以下一步是调试不同的请求:代理与非代理
VM1/MyAPP vs VM1:8585/MyAPP
所以我发现每次请求获得授权时它都会对请求进行身份验证 header.This 仅在代理版本中发生。
因此,对于 apache 2.2,您无法删除 headers。那是刚刚在 2.4 上添加的 于是又haproxy了,同样的方法试了强制取消授权header。它几乎奏效了。我遇到了一些问题,请求方法是 1 而不是 GET。奇...
长话短说现在很明显基本身份验证是问题所在。
如何解决这个问题?
更新:
我现在的问题是: 如何更改 KeycloakAuthenticationEntryPoint loginUri 以在配置中包含我的反向代理的子上下文? - 在 root 上有一个反向代理 "sso/login" 不会让我在同一台服务器上有超过 1 个 keycloak 应用程序。
我是怎么解决问题的:
1) 因此,第一步是在干扰 keycloak 授权过程或至少 spring 安全性的 apache 上禁用基本身份验证。
此后我开始注意到我总是被重定向到 root 上的 /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 适配器应用程序。为了改变 spring 端的行为,我用两个过程解决了它。 - 第一个是在 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"