我一直在使用SAML2.0和SpringBoot2.5.6,使用Okta作为身份提供者。在大多数情况下,我能够创建一个Web应用程序并与Okta的身份提供者集成。我所面临的问题与角色有关。我在Okta中指定的组不会转换为Security中的角色,也不清楚这种转换是如何在中发生的。在SAML断言中,group属性被命名为“group”,我可以在作为响应一部分的断言XML中看到这一点。但是Security并不把“组”属性理解为角色。
身份验证之后,SAML2Authentication对象将权限包含为ROLE_USER。如何将断言中的传入组属性转换为SAML2Authentication中的适当权限?否则,我无法将应用程序URL配置为适当的授权角色。
请帮我或指点我的方向。
发布于 2021-11-14 11:12:14
在Spring中,连接到SAML2身份验证过程的方法有很多种,但最常见、也似乎最推荐的方法是定制Security用于身份验证的OpenSamlAuthenticationProvider。
然而,这种方法在最近的版本中发生了许多变化。下面的例子是Kotlin,您必须自己将它翻译成Java (如果这是您想要的话)。另外,在哪个Security版本中使用Spring版本,您也必须自己了解,但是版本2.5.6肯定会将您放在下面的最后一个例子中。
Spring安全< 5.3.0
setAuthoritiesExtractor使添加一个从断言中提取权限/角色的方法变得非常容易。该方法应该返回一个Collection<GrantedAuthority>类型的对象。
.saml2Login()
.authenticationManager(
ProviderManager(
OpenSamlAuthenticationProvider().apply {
setAuthoritiesExtractor { a: Assertion? ->
// return a list of authorities based on the assertion
}
}
)
)Spring安全>= 5.3.0和< 5.4.0
setAuthoritiesExtractor被反对使用setResponseAuthenticationConverter的建议。不幸的是,这比以前的方法要复杂得多。
.saml2Login()
.authenticationManager(
ProviderManager(
OpenSamlAuthenticationProvider().apply {
setResponseAuthenticationConverter {
val defaultAuth = OpenSamlAuthenticationProvider.createDefaultResponseAuthenticationConverter().convert(it);
if (defaultAuth !== null && defaultAuth.isAuthenticated) {
val authoritiesLists = it.response.assertions.map { ass ->
// return a list of authorities based on the assertion
}
val authoritiesList = authoritiesLists.flatten().toSet()
Saml2Authentication(defaultAuth.principal as AuthenticatedPrincipal, defaultAuth.saml2Response, authoritiesList)
}
else
defaultAuth
}
}
)
)我不知道是否有更简单的方法,但在这里,我们基本上使用默认行为,但修改它的方式,我们想要的。在形式上,断言列表可能包含多个断言,因此我们通过使用多个列表来处理这些断言,这些列表随后被扁平化并转换为一个集合(只有在您愿意的情况下才可以使用第一个断言,因为通常只有一个)。
Spring安全>= 5.4.0
这一次改变的是,由于OpenSamlAuthenticationProvider使用了OpenSAML3,它的生命周期已经结束,并被OpenSAML4所取代,因此受到了反对。我们现在必须使用OpenSaml4AuthenticationProvider。除此之外,配置部分保持不变。
.saml2Login()
.authenticationManager(
ProviderManager(
OpenSaml4AuthenticationProvider().apply {
setResponseAuthenticationConverter {
val defaultAuth = OpenSaml4AuthenticationProvider.createDefaultResponseAuthenticationConverter().convert(it);
if (defaultAuth !== null && defaultAuth.isAuthenticated) {
val authoritiesLists = it.response.assertions.map { ass ->
// return a list of authorities based on the assertion
}
val authoritiesList = authoritiesLists.flatten().toSet()
Saml2Authentication(defaultAuth.principal as AuthenticatedPrincipal, defaultAuth.saml2Response, authoritiesList)
}
else
defaultAuth
}
}
)
)尽管如此,这是不可能的,您必须对项目中的包语句进行一些修改,以强制Security使用OpenSAML4而不是OpenSAML3 (由于向后兼容性这是默认的)。
下面是使用Gradle的样子
dependencies {
constraints {
implementation "org.opensaml:opensaml-core:4.1.1"
implementation "org.opensaml:opensaml-saml-api:4.1.1"
implementation "org.opensaml:opensaml-saml-impl:4.1.1"
}
...
}现在你准备好了!请记住,Saml2Authentication的第一个参数是用户主体(继承自AuthenticatedPrincipal),它也可以根据自己的愿望和需求进行定制。只要实现一个从AuthenticatedPrincipal继承的用户类,并将逻辑添加到响应身份验证转换器,就可以了。
链接
https://stackoverflow.com/questions/69956447
复制相似问题