web-dev-qa-db-fra.com

Comment supprimer le préfixe ROLE_ de Spring Security avec JavaConfig?

J'essaie de supprimer le préfixe "ROLE_" dans Spring Security. La première chose que j'ai essayée était:

http.servletApi().rolePrefix("");

Cela n'a pas fonctionné, j'ai donc essayé de créer un BeanPostProcessor comme suggéré dans http://docs.spring.io/spring-security/site/migrate/current/3-to-4/ html5/migrate-3-to-4-jc.html # m3to4-role-prefixing-disable . Cela n'a pas fonctionné non plus.

Enfin, j'ai essayé de créer mon propre SecurityExpressionHandler:

  @Override
  protected void configure(HttpSecurity http) throws Exception {
      http
          .authorizeRequests()
          .expressionHandler(webExpressionHandler())
          .antMatchers("/restricted").fullyAuthenticated()
          .antMatchers("/foo").hasRole("mycustomrolename")
          .antMatchers("/**").permitAll();
  }

  private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() {
      DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
      defaultWebSecurityExpressionHandler.setDefaultRolePrefix("");
      return defaultWebSecurityExpressionHandler;
  }

Cependant, cela ne fonctionne pas non plus. Si j'utilise "hasAuthority (roleName)" au lieu de hasRole, cela fonctionne comme prévu.

Est-il possible de supprimer le préfixe ROLE_ de la vérification hasRole de Spring Security?

13
Matt Raible

À partir de Spring 4.2, vous pouvez définir le préfixe avec un seul bean, comme décrit ici: https://github.com/spring-projects/spring-security/issues/4134

@Bean
GrantedAuthorityDefaults grantedAuthorityDefaults() {
    return new GrantedAuthorityDefaults(""); // Remove the ROLE_ prefix
}

Version XML:

<beans:bean id="grantedAuthorityDefaults" class="org.springframework.security.config.core.GrantedAuthorityDefaults">
    <beans:constructor-arg value="" />
</beans:bean>
19
Antoine Melki

La configuration suivante fonctionne pour moi.

@Override
public void configure(WebSecurity web) throws Exception {
    web.expressionHandler(new DefaultWebSecurityExpressionHandler() {
        @Override
        protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) {
            WebSecurityExpressionRoot root = (WebSecurityExpressionRoot) super.createSecurityExpressionRoot(authentication, fi);
            root.setDefaultRolePrefix(""); //remove the prefix ROLE_
            return root;
        }
    });
}
7
walsh

Si vous êtes avant 4.2 et utilisez des soi-disant votants (vous l'êtes si vous utilisez des annotations comme @hasRole, etc.), vous devez définir les beans ci-dessous dans le contexte:

@Bean
public DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() {
    DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler = new DefaultMethodSecurityExpressionHandler();
    defaultMethodSecurityExpressionHandler.setDefaultRolePrefix("");
    return defaultMethodSecurityExpressionHandler;
}

@Bean
public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler() {
    DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
    defaultWebSecurityExpressionHandler.setDefaultRolePrefix("");
    return defaultWebSecurityExpressionHandler;
}

Ces beans sont utilisés pour créer un contexte d'évaluation pour les expressions orthographiques et ils ont un defaultRolePrefix défini sur "ROLE_". Bien que cela dépende de votre cas d'utilisation. Celui-ci a fonctionné pour moi et surtout pas.

EDIT: répondre à une question sur la configuration xml -> bien sûr, cela peut être fait en xml. Tout est fait en Java peut être écrite en configuration xml. Voici un exemple (bien que je ne l'ai pas testé donc il pourrait y avoir une faute de frappe ou quelque chose):

<bean id="defaultWebSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
        <property name="defaultRolePrefix" value=""></property>
</bean>

<bean id="defaultMethodSecurityExpressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
        <property name="defaultRolePrefix" value=""></property>
</bean>
4
Piotr Tempes

Il semble que le nouveau GrantedAuthorityDefaults changera le préfixe du DefaultWebSecurityExpressionHandler et du DefaultMethodSecurityExpressionHandler, mais il ne modifie pas le RoleVoter.rolePrefix Configuré à partir de @EnableGlobalMethodSecurity.

Le RoleVoter.rolePrefix est ce qui est utilisé pour le style de sécurité de méthode @Secured("ADMIN").

Ainsi, avec la GrantedAuthorityDefaults, j'ai dû également ajouter cette classe CustomGlobalMethodSecurity pour remplacer les valeurs par défaut de RoleVoter.

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class CustomGlobalMethodSecurity extends GlobalMethodSecurityConfiguration {

    protected AccessDecisionManager accessDecisionManager() {
        AffirmativeBased accessDecisionManager = (AffirmativeBased) super.accessDecisionManager();

        //Remove the ROLE_ prefix from RoleVoter for @Secured and hasRole checks on methods
        accessDecisionManager.getDecisionVoters().stream()
                .filter(RoleVoter.class::isInstance)
                .map(RoleVoter.class::cast)
                .forEach(it -> it.setRolePrefix(""));

        return accessDecisionManager;
    }
}
3
Jeff Sheets

Si vous utilisez Spring Boot 2, vous pouvez créer ce bean pour remplacer le préfixe RoteVoter

@Bean
public GrantedAuthorityDefaults grantedAuthorityDefaults() {
    return  new GrantedAuthorityDefaults("<anything you want>");
}

Cela fonctionne car lorsque GlobalMethodSecurityConfiguration crée AccessDecisionManager dans la méthode GlobalMethodSecurityConfiguration.accessDecisionManager (). Voici l'extrait de code, notez la vérification nulle sur grantAuthorityDefaults

    protected AccessDecisionManager accessDecisionManager() {
    ....
    RoleVoter roleVoter = new RoleVoter();
    GrantedAuthorityDefaults grantedAuthorityDefaults =
            getSingleBeanOrNull(GrantedAuthorityDefaults.class);
    if (grantedAuthorityDefaults != null) {
        roleVoter.setRolePrefix(grantedAuthorityDefaults.getRolePrefix());
    }
    decisionVoters.add(roleVoter);
    decisionVoters.add(new AuthenticatedVoter());
    return new AffirmativeBased(decisionVoters);
}
0
Hung Tran

Je poste des solutions de travail résumées pour moi:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    /**
     * Allow skip ROLE_ when check permission using @Secured, like:
     *  @Secured({AuthorityConstants.ROLE_SYSTEM_ADMIN})
     */
    @Override
    protected AccessDecisionManager accessDecisionManager() {
        AffirmativeBased accessDecisionManager = (AffirmativeBased) super.accessDecisionManager();
        setAuthorityRolePrefix(accessDecisionManager, "");
        return accessDecisionManager;
    }

    private void setAuthorityRolePrefix(AffirmativeBased accessDecisionManager, String rolePrefix) {
        accessDecisionManager.getDecisionVoters().stream()
                .filter(RoleVoter.class::isInstance)
                .map(RoleVoter.class::cast)
                .forEach(it -> it.setRolePrefix(rolePrefix));
    }

    /**
     * Allow skip ROLE_ when check permission using @PreAuthorize, like:
     * @PreAuthorize("hasAnyRole('USER', 'SYSTEM_ADMIN')")
     */
    @Bean
    GrantedAuthorityDefaults grantedAuthorityDefaults() {
        return new GrantedAuthorityDefaults(""); // Remove the ROLE_ prefix
    }
}
0
chi nguyen