如何在Vaadin14中正确配置Spring Security实现Keycloak与DB双认证入口
问题原因及修复方案
核心问题
你的配置存在4个典型的多安全链配置冲突问题,导致认证请求无法匹配到对应的处理逻辑:
- 安全链路径匹配范围错误:两个安全链分别只匹配
/test**和/prod**,但测试环境的登录请求地址/login、注销地址/logout都没有匹配到任何自定义安全链,最终会使用全局的认证配置(被Keycloak的认证Provider覆盖),用Keycloak的逻辑校验数据库用户名密码,自然认证失败。 - 路径匹配规则写法错误:
/test**写法无法匹配/test/xxx这类子路径,Vaadin的内部请求如/test/vaadinServlet/UIDL都无法被当前安全链识别。 - 认证规则不匹配:数据库认证安全链要求用户有
USER角色,但你默认创建的测试用户角色是ACTOR,就算认证通过也会返回403权限不足。 - 全局AuthenticationManager冲突:你通过
configureGlobal注入了Keycloak的认证Provider到全局认证管理器,覆盖了数据库用户的认证逻辑,导致数据库用户的认证请求找不到对应的Provider。
具体修复步骤
- 修正安全链匹配范围
调整两个安全链的匹配规则,确保所有相关请求都能匹配到对应的处理链:- Keycloak安全链(Order 1)将匹配规则改为
/prod/**,同时将Keycloak的回调、注销路径都配置到/prod路径下,避免和测试环境路径冲突。 - 数据库认证安全链(Order 2)将原
.antMatcher("/test**")替换为.requestMatchers().antMatchers("/test/**", "/login", "/logout"),覆盖测试环境所有需要处理的路径。
- Keycloak安全链(Order 1)将匹配规则改为
- 隔离两个安全链的认证逻辑
不要使用全局的AuthenticationManager,分别给两个安全链配置独立的认证Provider:- Keycloak配置类中去掉
configureGlobal方法,重写configure(AuthenticationManagerBuilder auth)方法,在方法内注册Keycloak的认证Provider,仅作用于当前安全链。 - 数据库认证配置类中重写
configure(AuthenticationManagerBuilder auth)方法,指定使用当前类定义的userDetailsService,避免被全局配置覆盖。
- Keycloak配置类中去掉
- 修正角色匹配规则
把数据库认证安全链的.anyRequest().hasRole("USER")改为.anyRequest().hasRole("ACTOR"),或者把默认测试用户的角色改为USER,保持两者一致。 - 统一静态资源忽略规则
将configure(WebSecurity web)方法提到外层的ApplicationSecurityConfiguration类中,避免两个安全链静态资源规则不一致导致的资源拦截问题。
内容的提问来源于stack exchange,提问作者Tarek M. Ahmed
相关产品推荐
相关产品推荐

