2015-09-07 12 views
9

Ich versuche, Zugriffsregeln auf Methodenebene zu definieren, aber es funktioniert nicht, was auch immer.PreAuthorize funktioniert nicht auf 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"; 
    } 
} 

Immer wenn ich versuche/zuzugreifen v2/home user:user mit der Ausführung ganz gut, sollte es mir nicht einen Zugriff verweigert Fehler geben wegen ‚user 'nicht haben ROLE_ADMIN?

Ich denke eigentlich daran, Zugriffsregeln auf Methodenebene zu löschen und bei http() zu bleiben, aber ich muss wissen, warum es für mich nicht funktioniert.

Antwort

18

Ein häufiges Problem bei der Verwendung von PrePost-Annotationen auf Controllern ist, dass die Spring-Methodensicherheit auf Spring AOP basiert, das standardmäßig mit JDK-Proxys implementiert wird.

Das bedeutet, dass es auf der Serviceschicht funktioniert, die als Schnittstelle in die Controllerschicht injiziert wird, aber auf der Controllerschicht ignoriert wird, da Controller im Allgemeinen keine Schnittstellen implementieren.

Das folgende ist nur meine Meinung:

  • bevorzugte Art und Weise: die Pre Post Anmerkung
  • , wenn Sie (nicht wollen oder), können nicht auf Service-Ebene verschieben versuchen, Ihren Controller eine Schnittstelle implementieren alle kommentierten Methoden
  • als letzte Möglichkeit enthält, verwenden Proxy-Ziel-Klasse = true
+1

Danke für die Antwort. Ich habe versucht, die Annotation auf einer "CrudRepository" -Schnittstelle zu verwenden, und es hat gut funktioniert.Eine Schnittstelle zu jedem Controller zu haben, ist meiner Meinung nach irgendwie albern, da eine Schnittstelle nicht wirklich notwendig ist. 'proxy-target-class = true' hat keinen Unterschied gemacht, die Annotationen funktionieren immer noch nicht auf Controllern, haben jedoch einen Absturz verursacht (wenn sie auf true gesetzt sind), wenn die Annotation in der Repository-Schnittstelle enthalten ist. sun.proxy). Jedenfalls glaube ich, dass ich mich an die Regeln in der Sicherheitskonfiguration halte und vielleicht PreAuth für einige meiner Repositories verwende. – prettyvoid

+1

Eine andere Sache, die ich bemerkt habe, ich habe Beispiele gesehen, wo die @ PreAuthorize in einer 'Klasse' anstatt einer' Schnittstelle' verwendet wurde und es funktioniert. Ich frage mich, warum es für sie funktioniert, aber nicht für mich. – prettyvoid

+1

Aktivieren Aop im Anwendungskontext

6

ich hatte ein ähnliches Problem und t er folgende löste es:

1) Ich musste meine Methode öffentlich machen (d. h. machen Sie Ihre Methode nach Hause() public)

2) Ich habe hasRole zu verwenden, anstatt hasAuthority

+0

Ich hatte das gleiche Problem und machte die Methoden öffentlich es zu lösen! –

+0

machen die Controller-Methoden öffentlich für mich gelöst. – Piyush

0

Denn es macht auf Controller-Ebene arbeiten. Ich musste @EnableAspectJAutoProxy auf meine Konfigurationsklasse setzen. Beispiel:

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

} 
+0

meins funktioniert ohne diese @EnableAspectJAutoProxy Ich habe gerade @PreAuthorize ("hasAuthority ('ADMIN')") – valik

+0

warum ist das? @kripal kashyav – valik

1

Es gibt zwei verschiedene Wege, dies zu nutzen, ist ein Präfix und man ist es nicht. Und Sie vielleicht ändern @PreAuthorize("hasAuthority('ROLE_ADMIN')") zu @PreAuthorize("hasAuthority('ADMIN')") wird in Ordnung sein.

Als nächstes ist @PreAuthorize Quellcode.

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

und diese Quelle sollte hinzugefügt werden, wo und wie mein Controller darauf zugreifen? – valik

0

Sie müssen hinzufügen "@EnableGlobalMethodSecurity (prePostEnabled = true)" in Ihrem WebSecurityConfig.

Sie können es hier finden: http://www.baeldung.com/spring-security-expressions-basic

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 
Verwandte Themen