Scala服务作为SP,如何通过pac4j-saml 6.0.2触发SAML登录流程?
使用pac4j-saml 6.0.2触发SAML登录流程指引
问题背景
你有一个作为服务提供商(SP)的Scala服务,基于pac4j-saml 6.0.2版本对接Keycloak身份提供商(IdP)实现SAML认证。已定义如下路由和SAML配置,但不清楚如何通过访问/login触发SAML登录流程:
现有路由(routes.scala)
path("login"){ get { complete(StatusCodes.OK -> "OK") } }
现有SAML配置(SAMLConfigObject.scala)
class SAMLConfigObject { def constructConfigObject: Config = { val saml2Configuration = new SAML2Configuration() saml2Configuration.setKeystorePath("samlKeystore.jks") saml2Configuration.setKeystorePassword("pac4j-demo-passwd") saml2Configuration.setPrivateKeyPassword("pac4j-demo-passwd") saml2Configuration.setIdentityProviderMetadataPath("http://localhost:9090/realms/IdProvider/protocol/saml/descriptor") saml2Configuration.setIdentityProviderEntityId("http://localhost:9090/realms/IdProvider") val saml2Client: SAML2Client = new SAML2Client(saml2Configuration) saml2Client.setName("SAML2Client") val config = new Config(saml2Client) config } }
解决方案步骤
1. 添加pac4j Akka HTTP依赖
确保你的build.sbt中包含适配pac4j 6.x版本的Akka HTTP集成包:
libraryDependencies += "org.pac4j" %% "pac4j-akka-http" % "6.0.2"
2. 修改/login路由触发SAML认证
替换现有/login路由逻辑,使用pac4j的AuthenticateAction触发重定向到Keycloak的SAML登录页面:
import org.pac4j.akka.http.AuthenticateAction import org.pac4j.core.config.Config import akka.http.scaladsl.server.Directives._ // 初始化SAML配置实例 val samlConfig = new SAMLConfigObject().constructConfigObject path("login") { get { // 指定使用SAML2Client触发认证流程 AuthenticateAction(samlConfig, Some("SAML2Client")) } }
3. 添加回调路由处理IdP响应
Keycloak验证用户身份后,会将SAML断言回调到SP的指定路径,需新增路由处理该回调:
import org.pac4j.akka.http.CallbackAction path("callback") { get { // 解析SAML响应,完成认证会话建立 CallbackAction(samlConfig) } }
4. 完善SAML配置细节
现有配置缺少SP侧关键参数,需补充以匹配Keycloak的SP客户端配置:
class SAMLConfigObject { def constructConfigObject: Config = { val saml2Configuration = new SAML2Configuration() saml2Configuration.setKeystorePath("samlKeystore.jks") saml2Configuration.setKeystorePassword("pac4j-demo-passwd") saml2Configuration.setPrivateKeyPassword("pac4j-demo-passwd") saml2Configuration.setIdentityProviderMetadataPath("http://localhost:9090/realms/IdProvider/protocol/saml/descriptor") saml2Configuration.setIdentityProviderEntityId("http://localhost:9090/realms/IdProvider") // 新增:SP实体ID(需与Keycloak中配置的SP实体ID完全一致) saml2Configuration.setServiceProviderEntityId("http://localhost:8080/callback") // 新增:SP元数据生成地址,用于Keycloak导入SP配置 saml2Configuration.setServiceProviderMetadataPath("http://localhost:8080/callback?metadata=true") // 启用SP元数据自动生成 saml2Configuration.setGenerateServiceProviderMetadata(true) val saml2Client: SAML2Client = new SAML2Client(saml2Configuration) saml2Client.setName("SAML2Client") val config = new Config(saml2Client) // 配置会话存储(默认内存存储,生产环境可替换为分布式存储) config.setSessionStore(new org.pac4j.core.context.session.SessionStore()) config } }
5. 验证Keycloak配置一致性
确保Keycloak中你的SP客户端配置与上述参数匹配:
- 实体ID:与
setServiceProviderEntityId的值完全一致 - Valid Redirect URIs:包含回调URL(如
http://localhost:8080/callback) - SAML元数据源:可通过
http://localhost:8080/callback?metadata=true获取并导入Keycloak
流程说明
当用户访问/login时,AuthenticateAction会根据SAML配置生成重定向URL,引导用户到Keycloak的登录页面。用户完成身份验证后,Keycloak会将SAML断言发送到/callback路由,CallbackAction会解析断言、建立用户会话,之后你可以通过ProfileAction获取用户信息,或使用RequireAuthenticationAction保护需要登录才能访问的路由。
内容的提问来源于stack exchange,提问作者ntj
相关产品推荐
相关产品推荐

