我们有一个基于spring boot的微服务架构,我们有多个微服务器相互通信,还有一个连接到不同微服务的Javascript UI。
由于这是一个内部应用程序,我们需要将它们连接到我们的SAML2端点以提供SSO,因此将所有这些连接起来让我感到头疼。理想情况下,微服务在它们之间使用oAuth2(JWT)和UI,但用户身份验证是通过SAML2完成的
以下我想用此实现:
所以我尝试了很多不同的东西。我可以说的是:
我想我在努力的地方是oauth2资源服务器和SAML服务的连接点。
关于SAML我有以下工作正常:
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Value("${security.saml2.metadata-url}")
String metadataUrl;
@Value("${server.ssl.key-alias}")
String keyAlias;
@Value("${server.ssl.key-store-password}")
String password;
@Value("${server.port}")
String port;
@Value("${server.ssl.key-store}")
String keyStoreFilePath;
@Autowired
SAMLUserDetailsService samlUserDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/oauth/**").authenticated()
.and().exceptionHandling()
.and()
.authorizeRequests()
.antMatchers("/saml*").permitAll()
.anyRequest().authenticated()
.and()
.apply(saml()).userDetailsService(samlUserDetailsService)
.serviceProvider()
.keyStore()
.storeFilePath("saml/keystore.jks")
.password(this.password)
.keyname(this.keyAlias)
.keyPassword(this.password)
.and()
.protocol("https")
.hostname(String.format("%s:%s", "localhost", this.port))
.basePath("/")
.and()
.identityProvider()
.metadataFilePath(this.metadataUrl);
}
}
并且工作正常。因此当我点击受保护的端点时,我将被重定向并可以通过saml登录。我在samlUserDetailsService中获得了userdetails。
关于oauth我有这样的事情:
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore())
.tokenEnhancer(accessTokenConverter())
.authenticationManager(authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("ABC"); //needs to be changed using certificates
return converter;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("acme")
.secret("acmesecret")
.authorizedGrantTypes("refresh_token", "authorization_code")
.autoApprove(true)
.scopes("webapp")
.accessTokenValiditySeconds(60)
.refreshTokenValiditySeconds(3600);
}
}
这部分也适用于我有@EnableResourceServer
的其他微服务器据我了解OAuth部分,ClientDetailsServiceConfigurer只配置客户端应用程序(在我的情况下是其他微服务),我应该使用client_credentials类型的授权(但不确定)。但是我如何在SAML部分接线并不清楚......
作为替代方案,我正在考虑拆分它。创建一个OAuth授权服务的微服务和另一个执行SAML位的微服务。在这种情况下,如果用户通过身份验证,SAML微服务将连接到SAML并提供类似/ me的端点。然后,OAuth授权服务将使用SAML微服务检查用户是否在那里进行了身份验证,如果是这种情况,则提供令牌。关于刷新令牌,我也会这样做。 据我所知,我会在这个中实现这种逻辑 public void configure(ClientDetailsServiceConfigurer clients)抛出Exception {}方法。
如果有更好的方法,请告诉我!