web-dev-qa-db-fra.com

PreAuthorize ne fonctionne pas sur le contrôleur

J'essaie de définir des règles d'accès au niveau de la méthode, mais cela ne fonctionne pas vraiment.

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

Chaque fois que j'essaie d'accéder à/v2/home en utilisant user:user, il s'exécute correctement. Ne devrait-il pas me donner une erreur d'accès refusé en raison du fait que "l'utilisateur" n'a pas ROLE_ADMIN?

Je pense en fait à abandonner les règles d'accès au niveau de la méthode et à m'en tenir aux règles http (), mais je dois savoir pourquoi cela ne fonctionne pas pour moi.

13
prettyvoid

Un problème courant lié à l'utilisation d'annotations PrePost sur des contrôleurs est que la sécurité de la méthode Spring est basée sur Spring AOP, implémentée par défaut avec des mandataires JDK.

Cela signifie que cela fonctionne bien sur la couche de service injectée dans la couche contrôleur en tant qu'interfaces, mais que cette dernière est ignorée sur la couche contrôleur car le contrôleur n'implémente généralement pas les interfaces.

Ce qui suit est juste mon avis:

  • manière préférée: déplacer la pré-annotation sur la couche de service
  • si vous ne pouvez pas (ou ne voulez pas), essayez de faire en sorte que votre contrôleur implémente une interface contenant toutes les méthodes annotées.
  • comme dernier moyen, utilisez proxy-target-class = true
21
Serge Ballesta

Vous devez ajouter @EnableGlobalMethodSecurity(prePostEnabled = true) dans votre WebSecurityConfig.

Vous pouvez le trouver ici: http://www.baeldung.com/spring-security-expressions-basic

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
11
Eric Zürcher

J'ai eu un problème similaire et ce qui suit l'a résolu:

1) Je devais rendre ma méthode publique (c'est-à-dire rendre votre méthode home () public) 

2) Je dois utiliser hasRole au lieu de hasAuthority 

7
Horowitzathome

Pour que cela fonctionne sur la couche contrôleur ..__, j'ai dû mettre @EnableAspectJAutoProxy sur ma classe de configuration . Exemple: 

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

}
2
kripal kashyav

Il y a deux façons différentes d’utiliser ceci: l’une consiste à préfixer l’autre et l’autre n’est pas . Et vous pouvez peut-être remplacer @PreAuthorize("hasAuthority('ROLE_ADMIN')") par @PreAuthorize("hasAuthority('ADMIN')"), ce qui sera correct.

est le suivant: code source @PreAuthorize.

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);
}
1
beautifulcode

Si vous avez un fichier de contexte xml pour vos beans de sécurité et un fichier distinct pour votre contexte web/servlet, vous devez également ajouter:

<security:global-method-security pre-post-annotations="enabled"/>

à votre contexte web-context.xml/servlet. Ce n'est pas suffisant pour simplement l'ajouter dans le contexte de sécurité xml.

Ce n'est pas hérité dans des contextes enfants.

HTH 

1
Chris