Spring Security SAML断言到角色的转换



我一直在使用SAML 2.0和Spring Boot 2.5.6,并使用Okta作为身份提供程序。在大多数情况下,我已经能够创建一个Web应用程序并与Okta的Identity提供商集成。我面临的问题与角色有关。我在Okta中分配的组没有转换为Spring Security中的角色,也不清楚这种转换应该如何在Spring Security for SAML中发生。在SAML断言中,组属性被命名为";组";我可以在作为响应一部分的断言XML中看到这一点。但是Spring Security不理解";组";属性作为角色。

在身份验证之后,SAML2Authentication对象包含作为ROLE_USER的Authority。如何将Assertion中的传入组属性转换为SAML2Authentication中的适当权限?否则,我无法将应用程序URL配置为用于授权的适当角色。

请帮忙或给我指个方向

在Spring Boot中,有多种方法可以挂接SAML2身份验证过程,但最常见且似乎最推荐的方法是自定义Spring Security用于身份验证的OpenSamlAuthenticationProvider

然而,在最近的版本中,这种方法发生了很多变化。下面的例子是Kotlin中的,你必须自己把它翻译成Java(如果你想要的话(。此外,在哪个Spring Boot版本中使用哪个Spring Security版本,您还必须自己了解,但2.5.6版本肯定会将您置于下面的最后一种情况。

Spring Security<5.3.0

setAuthoritiesExtractor使添加一个从断言中提取权限/角色的方法变得容易。该方法应返回一个类型为Collection<GrantedAuthority>的对象。

.saml2Login()
.authenticationManager(
ProviderManager(
OpenSamlAuthenticationProvider().apply {
setAuthoritiesExtractor { a: Assertion? ->
// return a list of authorities based on the assertion
}
}
)
)

弹簧安全>=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
}
}
)
)

我不知道是否有更简单的方法可以做到这一点,但在这里,我们基本上使用默认行为,但按照我们想要的方式修改它。从形式上讲,断言列表可能包含多个断言,所以我们通过使用多个列表来处理这一问题,这些列表然后被展平并变成一个集合(只有在你喜欢的情况下,你才能使用第一个断言,因为通常只有一个(。

弹簧安全>=5.4.0

这次发生的变化是,OpenSamlAuthenticationProvider由于使用了OpenSAML3而被弃用,而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
}
}
)
)

尽管如此,这不会开箱即用,您必须对项目中的包语句进行一些修改,以强制Spring 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的用户类,并将逻辑添加到响应身份验证转换器中,就可以开始了。

链接

  • SAML2示例配置

最新更新