2016-06-20 15 views
4

ich eine ganz besondere Anforderungen in meinem Frühjahr Boot-Web-Anwendung haben: Ich habe interne und externe Benutzer. Interne Benutzer anmelden, um die Web-Anwendung von keycloak Authentifizierung verwenden (sie sind in der Web-Anwendung arbeiten können), aber unsere externen Benutzer anmelden durch einfache Feder-Boot-Authentifizierung (was sie tun können, ist nur ein paar Dateien von Web-Anwendung erzeugen zum Download)SpringBoot mehrere Authentifizierungs Adapter

Was ich tun möchte, ist, mehr Authentifizierungsmodell haben: all den Pfad außer/download/* authentifiziert wird durch unsere Keycloak Authentifizierung, aber der Pfad/download/* von SpringBoot Standardauthentifizierung authentifiziert werden.

Im Moment habe ich die folgenden:

@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"); 
     } 

    } 
} 

Aber es funktioniert nicht gut, denn jedes Mal, wenn der externe Benutzer möchte etwas herunterladen (/ download/export/Test), fordert sie das Anmeldeformular , aber nachdem Sie den korrekten Benutzernamen und das Passwort des externen Benutzers eingegeben haben, wird das Anmeldeformular für die Keycloak-Authentifizierung angezeigt.

Ich bekomme keine Fehler nur eine Warnung:

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.springframew[email protected]3fb541cc: Principal: [email protected]: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER1; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]957e: RemoteIpAddress: 127.0.0.1; SessionId: 4C1BD3EA1FD7F50477548DEC4B5B5162; Granted Authorities: ROLE_USER1 

Haben Sie Ideen?

Antwort

1

Der Schlüssel für mehrere HttpSecurity ist die ‚Sonderfälle‘ vor dem normalen zu registrieren. Mit anderen Worten, der Authentifizierungsadapter /download/export/test sollte vor dem Schlüsselcloak-Adapter registriert werden.

Eine weitere wichtige Sache zu beachten, sobald eine Authentifizierung erfolgreich ist, wird kein anderer Adapter aufgerufen (so ist die .regexMatcher("^(?!.*/download/export/test)") nicht notwendig). Weitere Informationen zu Multiple HttpSecurity finden Sie unter here.

Im Folgenden finden Sie Code mit minimalen Änderungen:

@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) 
    @Order(2) //Order is 2 -> 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()); 
     } 

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

    } 
} 
+0

Dies gilt nicht für mein Projekt. Wenn die erste WebSecurityConfig (in meinem Fall die Basissicherheit) den Benutzer erfolgreich authentifiziert, versucht KeycloakWebSecurityConfiguratorAdapter immer noch, sie zu authentifizieren und sendet 401-Antwort zusammen mit NOT_ATTEMPTED-Code. – nejckorasa

0

ich einige Kopfschmerzen erlebt, wenn neben Keycloak Authentifizierung Standardauthentifizierung Implementierung, da noch mehrere WebSecurityAdapter Implementierungen ‚durch das Buch‘, das Keycloak Authentifizierungsfilter genannt, während das tut, auch wenn die Basisauthentifizierung erfolgreich war.

Der Grund liegt hier: http://www.keycloak.org/docs/latest/securing_apps/index.html#avoid-double-filter-bean-registration

Wenn Sie also den Keycloak Spring Security Adapter zusammen mit Frühlings-Stiefel, stellen Sie sicher, diese beiden Bohnen (zusätzlich zu der gültigen Antwort von Jacob von Lingen) hinzuzufügen:

@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"); 
     } 

    } 
}