Я пытаюсь удалить префикс "ROLE_" в Spring Security. Первое, что я попробовал, было:
http.servletApi().rolePrefix("");
Это не сработало, поэтому я попытался создать BeanPostProcessor
как предложено в http://docs.spring.io/spring-security/site/migrate/current/3-to-4/html5/migrate-3-to-4 -jc.html # m3to4-role-prefixing-disable. Это тоже не сработало.
Наконец, я попытался создать свой собственный 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;
}
Однако это тоже не работает. Если я использую hasAuthority (roleName) вместо hasRole
, он будет работать как положено.
Можно ли удалить префикс ROLE_ из проверки hasRole Spring Security?
Ответ 1
Начиная с Spring 4.2, вы можете определить префикс с одним компонентом, как описано здесь: https://github.com/spring-projects/spring-security/issues/4134
@Bean
GrantedAuthorityDefaults grantedAuthorityDefaults() {
return new GrantedAuthorityDefaults(""); // Remove the ROLE_ prefix
}
XML версия:
<beans:bean id="grantedAuthorityDefaults" class="org.springframework.security.config.core.GrantedAuthorityDefaults">
<beans:constructor-arg value="" />
</beans:bean>
Ответ 2
Следующая конфигурация работает для меня.
@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;
}
});
}
Ответ 3
Если вы до 4.2 и используете так называемые избиратели (вы, если используете аннотации, такие как @hasRole и т.д.), вам нужно определить ниже beans в контексте:
@Bean
public DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() {
DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler = new DefaultMethodSecurityExpressionHandler();
defaultMethodSecurityExpressionHandler.setDefaultRolePrefix("");
return defaultMethodSecurityExpressionHandler;
}
@Bean
public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler() {
DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
defaultWebSecurityExpressionHandler.setDefaultRolePrefix("");
return defaultWebSecurityExpressionHandler;
}
Эти beans используются для создания контекста оценки для выражений заклинаний, и у них установлен параметр по умолчанию RolePrefix, равный "ROLE_". Хотя это зависит от вашего варианта использования. Эта работа для меня и выше не сделала.
EDIT: ответ на вопрос о конфигурации xml → конечно, это можно сделать в xml. Все, что сделано в конфигурации java, можно записать в xml-конфигурации. Вот пример (хотя я не тестировал его, поэтому может быть опечатка или что-то еще):
<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
Похоже, что новый GrantedAuthorityDefaults
изменит префикс для DefaultWebSecurityExpressionHandler
и DefaultMethodSecurityExpressionHandler
, но он не изменяет настройку RoleVoter.rolePrefix
, настроенную из @EnableGlobalMethodSecurity
.
RoleVoter.rolePrefix - это то, что используется для стиля безопасности метода @Secured("ADMIN")
.
Поэтому наряду с GrantedAuthorityDefaults
мне пришлось также добавить этот класс CustomGlobalMethodSecurity
чтобы переопределить значения по умолчанию для 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;
}
}
Ответ 5
Если вы используете Spring Boot 2, вы можете создать этот bean-компонент для переопределения префикса RoteVoter.
@Bean
public GrantedAuthorityDefaults grantedAuthorityDefaults() {
return new GrantedAuthorityDefaults("<anything you want>");
}
Это работает потому, что когда GlobalMethodSecurityConfiguration создает AccessDecisionManager в методе GlobalMethodSecurityConfiguration.accessDecisionManager(). Вот фрагмент кода, обратите внимание на нулевую проверку на предоставленном АвторизацииDefaults
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);
}
Ответ 6
Я публикую краткие рабочие решения для меня:
@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
}
}