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?
À 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>
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;
}
});
}
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>
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;
}
}
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);
}
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
}
}