sec:authorize 不适用于自定义角色

Posted

技术标签:

【中文标题】sec:authorize 不适用于自定义角色【英文标题】:sec:authorize does not work with custom role 【发布时间】:2017-01-01 16:17:40 【问题描述】:

我有一些自定义角色,例如:

<span sec:authentication="principal.authorities">[MENU_USER, BUTTON_ADD_USER,ROLE_USER, MENU_PRIVILEGE, BUTTON_EDIT_USER]</span>
     <div sec:authorize="hasRole('MENU_USER')">
         <span>This content is only shown to administrators.</span>
     </div>

使用'ROLE_USER'时,“span”中的文字可以正常显示,但使用其他角色时,文字无法显示。然后我在我的自定义角色中添加了'ROLE_'前缀,它又变得正常了。

我尝试像这样删除“ROLE_”前缀约束:

@Bean
AccessDecisionManager accessDecisionManager() 
    RoleVoter voter = new RoleVoter();
    voter.setRolePrefix("");
    List<AccessDecisionVoter<? extends Object>> voters= new ArrayList<>();

    voters.add(new WebExpressionVoter());
    voters.add(voter);
    voters.add(new AuthenticatedVoter());
    AffirmativeBased decisionManger = new AffirmativeBased(voters);
    return decisionManger;


@Override
protected void configure(HttpSecurity http) throws Exception 
    http
        .authorizeRequests()
            .accessDecisionManager(accessDecisionManager())
            .antMatchers("/webjars/**", "/login").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login")
            .permitAll()
            .loginProcessingUrl("/j_spring_security_check")
            .usernameParameter("j_username")
            .passwordParameter("j_password")
            .defaultSuccessUrl("/home", true)
            .failureUrl("/test")
            .and()

         //logout is    
        .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/login?logout")
        .permitAll();

它也不起作用。知道如何删除强制性的“ROLE_”前缀吗?

【问题讨论】:

检查***.com/questions/21620076/…和***.com/questions/10939792/… 【参考方案1】:

我的spring security升级到4.0.3导致的问题。根据文档Spring security doc,

默认情况下,如果提供的角色不以“ROLE_”开头,它将是 添加。这可以通过修改 defaultRolePrefix on DefaultWebSecurityExpressionHandler。

我已将以下代码添加到我的 SecurityConfig.java 中,问题已解决。

@Bean
DefaultWebSecurityExpressionHandler webSecurityExpressionHandler() 
    DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
    handler.setDefaultRolePrefix("");
    return handler;

后来,我从spring security migrating找到了官方修复

可以使用 BeanPostProcessor 禁用自动 ROLE_ 前缀 类似于以下内容:

 package sample.role_;

 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.config.BeanPostProcessor;
 import org.springframework.core.PriorityOrdered;
 import   org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource;
 import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
 import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;

 public class DefaultRolesPrefixPostProcessor implements BeanPostProcessor,   PriorityOrdered 

@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
        throws BeansException 

    // remove this if you are not using JSR-250
    if(bean instanceof Jsr250MethodSecurityMetadataSource) 
        ((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(null);
    

    if(bean instanceof DefaultMethodSecurityExpressionHandler) 
        ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(null);
    
    if(bean instanceof DefaultWebSecurityExpressionHandler) 
        ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(null);
    
    if(bean instanceof SecurityContextHolderAwareRequestFilter) 
        ((SecurityContextHolderAwareRequestFilter)bean).setRolePrefix("");
    
    return bean;


@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
        throws BeansException 
    return bean;


@Override
public int getOrder() 
    return PriorityOrdered.HIGHEST_PRECEDENCE;


然后将其定义为 Bean:

 @Bean
 public static DefaultRolesPrefixPostProcessor defaultRolesPrefixPostProcessor() 
    return new DefaultRolesPrefixPostProcessor();

【讨论】:

以上是关于sec:authorize 不适用于自定义角色的主要内容,如果未能解决你的问题,请参考以下文章

sec:authorize from thymeleaf 可以用于多个角色吗

NetSuite 上的子公司 Navigator 不适用于自定义角色

SetCurrentConsoleFontEx() 不适用于自定义安装的字体

Excel 自定义功能不适用于工作表

如何使用 <sec:authorize access="hasRole('ROLES)"> 来检查多个角色?

自定义授权适用于操作级别,但不适用于控制器级别