Spring Boot keycloak和基本身份验证一起在同一个项目中

时间:2016-06-21 11:01:49

标签: spring spring-mvc authentication spring-security keycloak

我遇到Spring Boot安全问题。我想要的是在Spring Boot中同时为同一个项目进行两种不同的身份验证。一个是除'/ download / export / *'之外的所有路径的SSO(keycloak身份验证),另一个是Spring Boot基本身份验证。 这是我的配置文件:

@Configuration 
@EnableWebSecurityp 
public class MultiHttpSecurityConfig {
@Configuration
@Order(1)
public static class DownloadableExportFilesSecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
    http
            .antMatcher("/download/export/test")
            .authorizeRequests()
            .anyRequest().hasRole("USER1")
            .and()
            .httpBasic();    }

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
    auth.inMemoryAuthentication()
            .withUser("user").password("password1").roles("USER1");
}
}

@Configuration
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public static class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
{
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
    auth.authenticationProvider(keycloakAuthenticationProvider());
}

@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy()
{
    return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}

@Override
protected void configure(HttpSecurity http) throws Exception
{
    super.configure(http);
    http
            .regexMatcher("^(?!.*/download/export/test)")
            .authorizeRequests()
            .anyRequest().hasAnyRole("ADMIN", "SUPER_ADMIN")
            .and()
            .logout().logoutSuccessUrl("/bye");

}
}

以上代码的问题如下: 如果我请求url'/ download / export / test',那么它会询问我的用户名/密码(基本身份验证)。成功登录后,它再次询问我的用户名/密码(但这次是keycloak身份验证),即使从SecurityConfig(Keycloak Adapter)中排除了请求的URL。

它只给我一个警告:

2016-06-20 16:31:28.771  WARN 6872 --- [nio-8087-exec-6] o.k.a.s.token.SpringSecurityTokenStore   : Expected a KeycloakAuthenticationToken, but found org.springframework.security.authentication.UsernamePasswordAuthenticationToken@3fb541cc: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER1; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: 4C1BD3EA1FD7F50477548DEC4B5B5162; Granted Authorities: ROLE_USER1

您对如何一起使用keycloak和基本身份验证有什么想法吗?

非常感谢! 卡罗

2 个答案:

答案 0 :(得分:6)

问题解释

您遇到的问题是use strict; use warnings; use Time::Piece; use Time::Seconds; my $str = '2018-02-05 12:00:00'; my $format = '%Y-%m-%d %H:%M:%S'; my $tp = localtime->strptime($str, $format); $tp += ONE_HOUR * 48; print $tp->strftime($format); 拦截了每个使用HTTP授权标头的请求。如果您的请求未通过Keycloak进行身份验证(即使您已通过任何其他身份验证提供程序进行身份验证! - 在您使用基本身份验证的情况下),您始终会被重定向到Keycloak&# 39; s登录页面(在您的情况下)或获取401 Unauthorized(如果KeycloakAuthenticationProcessingFilter.java中的Keycloak客户端配置为仅承载)。

默认情况下,如果请求与keycloak.json匹配,则会调用KeycloakAuthenticationProcessingFilter.java

KeycloakAuthenticationProcessingFilter.DEFAULT_REQUEST_MATCHER

这意味着任何与DEFAULT_LOGIN_URL( / sso / login OR 匹配的请求都包含授权HTTP标头(在您的情况下) OR access_token 作为查询参数,将由public static final RequestMatcher DEFAULT_REQUEST_MATCHER = new OrRequestMatcher( new AntPathRequestMatcher(DEFAULT_LOGIN_URL), new RequestHeaderRequestMatcher(AUTHORIZATION_HEADER), new QueryParamPresenceRequestMatcher(OAuth2Constants.ACCESS_TOKEN) ); 处理。

这就是为什么你必须用你自己的实现替换KeycloakAuthenticationProcessingFilter.java,当你的请求通过基本身份验证进行身份验证时,它会跳过调用RequestHeaderRequestMatcher(AUTHORIZATION_HEADER)

解决方案

以下是一个完整的解决方案,使您可以在相同的路径上同时使用基本身份验证和Keycloak身份验证。请特别注意 IgnoreKeycloakProcessingFilterRequestMatcher 实现,该实现将替换默认的 RequestHeaderRequestMatcher 。此匹配器仅匹配包含授权HTTP标头的请求,该标头的值不以KeycloakAuthenticationProcessingFilter.java为前缀。

在下面的示例中,具有角色"Basic "的用户可以访问TESTER,而具有/download/export/testADMIN角色的用户可以使用所有其他路径(我认为,在您的角色中) case,是Keycloak服务器上的帐户。)

SUPER_ADMIN

答案 1 :(得分:0)

我通过在KeycloakAuthenticationProcessingFilter上为路径配置例外来解决这个问题:

...
@Configuration
@Order(2)
static class KeyCloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

@Bean
public KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception {
    KeycloakAuthenticationProcessingFilter filter = new KeycloakAuthenticationProcessingFilter(
            authenticationManagerBean()
            , new AndRequestMatcher(
               KeycloakAuthenticationProcessingFilter.DEFAULT_REQUEST_MATCHER,
               new NegatedRequestMatcher(new AntPathRequestMatcher(YOUR_BASIC_AUTHD_PATH))));
    filter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy());
    return filter;
}