我的 Spring Boot Web 应用程序有一个非常特殊的要求:
我有内部和外部用户。内部用户使用keycloak认证登录web应用(他们可以在web应用中工作),而我们的外部用户通过简单的Spring Boot认证登录(他们可以做的只是下载一些web应用生成的文件)

我想要做的是拥有多个身份验证模型:
除了/download/* 之外的所有路径都需要通过我们的 Keycloak 认证进行认证,但是路径/download/* 需要通过 SpringBoot 基本认证进行认证。

目前我有以下几点:

@Configuration 
@EnableWebSecurity 
public class MultiHttpSecurityConfig { 
 
    @Configuration 
    @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class) 
    @Order(1) 
    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"); 
        } 
 
    } 
 
    @Configuration 
    @Order(2) 
    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"); 
        } 
 
    } 
} 

但是效果不好,因为每次外部用户想要下载东西(/download/export/test),都会提示登录表单,但是输入正确的外部用户用户名和密码后,比提示keycloak认证登录形式。

我没有收到任何错误只是警告:
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 身份验证旁边实现基本身份验证时,我遇到了一些麻烦,因为在“按书”执行多个 WebSecurityAdapter 实现时,即使基本身份验证成功,也会调用 Keycloak 身份验证过滤器。

原因就在这里:
http://www.keycloak.org/docs/latest/securing_apps/index.html#avoid-double-filter-bean-registration

因此,如果您将 Keycloak Spring Security Adapter 与 Spring Boot 一起使用,请确保添加这两个 bean(除了 Jacob von Lingen 的有效答案):

@Configuration 
@EnableWebSecurity 
public class MultiHttpSecurityConfig { 
 
    @Configuration 
    @Order(1) //Order is 1 -> First the special case 
    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) 
    //no Order, will be configured last => All other urls should go through the keycloak adapter 
    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()); 
        } 
 
        // necessary due to http://www.keycloak.org/docs/latest/securing_apps/index.html#avoid-double-filter-bean-registration 
        @Bean 
        public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(KeycloakAuthenticationProcessingFilter filter) { 
            FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter); 
            registrationBean.setEnabled(false); 
            return registrationBean; 
        } 
        // necessary due to http://www.keycloak.org/docs/latest/securing_apps/index.html#avoid-double-filter-bean-registration 
        @Bean 
        public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(KeycloakPreAuthActionsFilter filter) { 
            FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter); 
            registrationBean.setEnabled(false); 
            return registrationBean; 
        } 
 
 
        @Override 
        protected void configure(HttpSecurity http) throws Exception  
        { 
            super.configure(http); 
            http 
                .authorizeRequests() 
                .anyRequest().hasAnyRole("ADMIN", "SUPER_ADMIN") 
                .and() 
                .logout().logoutSuccessUrl("/bye"); 
        } 
 
    } 
} 


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!