2015-09-07 18 views
9

Sto provando a definire le regole di accesso a livello di metodo ma non funziona come mai.PreAuthorize non funziona su Controller

SecurityConfiguration

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 
    @Override 
    public void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.inMemoryAuthentication(). 
       withUser("user").password("user").roles("USER").and(). 
       withUser("admin").password("admin").roles("ADMIN"); 
    } 
    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
       .sessionManagement() 
       .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
       .and() 
       .authorizeRequests() 
       .antMatchers("/v2/**").authenticated() 
       .and() 
       .httpBasic() 
       .realmName("Secure api") 
       .and() 
       .csrf() 
       .disable(); 
    } 
} 

ExampleController

@EnableAutoConfiguration 
@RestController 
@RequestMapping({"/v2/"}) 
public class ExampleController { 
    @PreAuthorize("hasAuthority('ROLE_ADMIN')") 
    @RequestMapping(value = "/home", method = RequestMethod.GET) 
    String home() { 
     return "Hello World"; 
    } 
} 

Ogni volta che provo ad accedere/v2/casa utilizzando user:user esegue bene, non dovrebbe che mi darà un errore di accesso negato a causa di 'user 'non avendo ROLE_ADMIN?

In realtà sto pensando di abbandonare le regole di accesso a livello di metodo e rispettare le regole della formica http(), ma devo sapere perché non funziona per me.

risposta

18

Un problema comune con l'utilizzo delle annotazioni PrePost sui controller è che la sicurezza del metodo Spring è basata su Spring AOP, che per impostazione predefinita è implementata con i proxy JDK.

Ciò significa che funziona correttamente sul livello di servizio che viene iniettato nel livello controller come interfacce, ma viene ignorato sul livello controller perché il controller generalmente non implementa le interfacce.

Quello che segue è solo la mia opinione:

  • modo preferito: spostare il palo annotazioni pre sul livello di servizio
  • se non si può (o non vuole), cercare di avere il controller implementare un'interfaccia contenente tutti i metodi annotati
  • come ultima modo, all'utente proxy-porta-classe = true
+1

Grazie per la risposta. Ho provato a utilizzare l'annotazione su un'interfaccia 'CrudRepository' e ha funzionato bene.Avere un'interfaccia per ogni controller è piuttosto sciocco secondo me, in quanto un'interfaccia non è realmente necessaria. 'proxy-target-class = true' non ha fatto la differenza, le annotazioni continuano a non funzionare sui controller, tuttavia ha causato un arresto anomalo (se impostato su true) quando ha l'annotazione all'interno dell'interfaccia del repository (Can not subclass com. sun.proxy). Comunque penso che seguirò le regole nella configurazione di sicurezza, e forse userò PreAuth su alcuni dei miei repository. – prettyvoid

+1

Un'altra cosa che ho notato, ho visto esempi in cui @PreAuthorize è stato utilizzato in un 'class' invece che in un'interfaccia' e dovrebbe funzionare .. Mi chiedo perché funzioni per loro ma non per me. – prettyvoid

+1

Abilita Aop nel contesto dell'applicazione

6

ho avuto un problema simile e t ha risolto:

1) Ho dovuto rendere pubblico il mio metodo (ad es. rendere il vostro metodo di casa() pubblico)

2) devo usare hasRole invece di hasAuthority

+0

Ho avuto lo stesso problema e rendere i metodi pubblici lo ha risolto! –

+0

rendendo i metodi del controllore pubblici risolti per me. – Piyush

0

per renderlo lavorare sul livello di controllo. Ho dovuto mettere @EnableAspectJAutoProxy sulla mia classe di configurazione. Esempio:

@Configuration 
@EnableWebMvc 
@EnableAspectJAutoProxy 
@ComponentScan(basePackages = { "com.abc.fraud.ts.userservices.web.controller" }) 
public class WebConfig extends WebMvcConfigurerAdapter{ 

} 
+0

il mio ha funzionato senza questo @EnableAspectJAutoProxy Ho appena usato @PreAuthorize ("hasAuthority ('ADMIN')") – valik

+0

perché? @kripal kashyav – valik

1

Ci sono due modi diversi di usare questo, si è prefisso e uno non è. E forse cambi @PreAuthorize("hasAuthority('ROLE_ADMIN')") a @PreAuthorize("hasAuthority('ADMIN')") sarà ok.

successivo è @PreAuthorize codice sorgente.

private String defaultRolePrefix = "ROLE_"; 
public final boolean hasAuthority(String authority) { 
    return hasAnyAuthority(authority); 
} 

public final boolean hasAnyAuthority(String... authorities) { 
    return hasAnyAuthorityName(null, authorities); 
} 

public final boolean hasRole(String role) { 
    return hasAnyRole(role); 
} 

public final boolean hasAnyRole(String... roles) { 
    return hasAnyAuthorityName(defaultRolePrefix, roles); 
} 
+0

e questa fonte dovrebbe essere aggiunta dove e come viene accedita al mio controller? – valik

0

si deve aggiungere "@EnableGlobalMethodSecurity (prePostEnabled = true)" nella vostra WebSecurityConfig.

Lo si può trovare qui: http://www.baeldung.com/spring-security-expressions-basic

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 
Problemi correlati