@胡海龙 2020-01-17 14:34 采纳率: 33.3%
浏览 986

SpringBoot Security 在用了动态权限配置后权限继承(RoleHierarchy)失效

在使用hasRole("admin")这种方式配置权限时使用RoleHierarchy实现权限继承
是可以的,但是使用了数据库动态配置权限后继承失效,amdin不能访问user
下的接口了

@Configuration
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    SysUserServiceImpl sysUserService;
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        log.info("run custom user service");
        auth.userDetailsService(sysUserService);
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        log.info("run security configuation");
        http.authorizeRequests()
//      .antMatchers("/admin/**").hasRole("admin")
//      .antMatchers("/menu/**").hasRole("user")
//      .antMatchers("/user/**").hasRole("user")
        .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
            @Override
            public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                object.setSecurityMetadataSource(cfisms());
                object.setAccessDecisionManager(cadm());
                return object;
            }

        })
        .and()
        .formLogin()
        .loginProcessingUrl("/login").permitAll()
        .and()
        .csrf().disable();
    }

    @Bean
    RoleHierarchy roeHierarchy() {
        RoleHierarchyImpl roeImpl = new RoleHierarchyImpl();
        String hierarchy = "ROLE_admin > ROLE_user";
        roeImpl.setHierarchy(hierarchy);
        return roeImpl;
    }
    @Bean
    CustomFilterInvocationSecurityMetadataSource cfisms() {
        return new CustomFilterInvocationSecurityMetadataSource();
    }
    @Bean
    CustomAccessDecisionManager cadm() {
        return new CustomAccessDecisionManager();
    }

}

user

@Component
@Slf4j
public class SysUser implements Serializable,UserDetails{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String id;
    private String username;
    private String password;
    private String trueName;
    private String note;
    private String avator;
    private String tel;
    private String address;
    private Integer pageNo;
    private Integer pageSize;
    private List<Role> roles;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        log.info("password:"+password);
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getTrueName() {
        return trueName;
    }

    public void setTrueName(String trueName) {
        this.trueName = trueName;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public String getAvator() {
        return avator;
    }

    public void setAvator(String avator) {
        this.avator = avator;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Integer getPageNo() {
        return pageNo;
    }

    public void setPageNo(Integer pageNo) {
        this.pageNo = pageNo;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public static long getSerialversionuid() {
        return serialVersionUID;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return SysUser.class.getName().toString();
    }
//  security getter and setter
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        // get user permissions that already have
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for(Role role : roles) {
            authorities.add(new SimpleGrantedAuthority(role.getRole()));
            log.info(role.getRole());
        }
        return authorities;
    }

    @Override
    public boolean isAccountNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isEnabled() {
        // TODO Auto-generated method stub
        return true;
    }

}

自定义FilterInvocationMetadataSource

@Component
@Slf4j
public class CustomFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Autowired
    ServiceUrlMapper serviceUrlMapper;
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        //use AntPathMatcher matching rule
        String requestUrl = ((FilterInvocation)object).getRequestUrl();
        log.info("request url:"+requestUrl);
        //select all service url
        List<ServiceUrl> urls = serviceUrlMapper.select();
        for(ServiceUrl url : urls) {
            if(antPathMatcher.match(url.getUrl(), requestUrl)) {
                List<Role>roles = url.getRoles();
                String[]roleArr = new String[roles.size()];
                for(int i=0; i<roleArr.length; i++) {
                    roleArr[i] = roles.get(i).getRole();
                    log.info("role:"+roleArr[i]);

                }
                //return role info
                return SecurityConfig.createList(roleArr);
            }
        }
        return SecurityConfig.createList("ROLE_LOGIN");
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }

}

自定义AccessDecisionManager

@Component
@Slf4j
public class CustomAccessDecisionManager implements AccessDecisionManager {
    /**
     * decide current user permissions
     * @param authentication user login info
     * @param object FilterInvacation , it can obtain request info
     * @param configAttributes FilterInvocationSecurityMetadataSource return by getAttributes
     */
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {
        Collection<? extends GrantedAuthority> auths = authentication.getAuthorities();
        for(ConfigAttribute configAttribute : configAttributes) {   //configAttributes from customFilterInvocationMetadataSource
            if("ROLE_LOGIN".equals(configAttribute.getAttribute())&&auths instanceof UsernamePasswordAuthenticationToken) {
                log.info("current user:ROLE_LOGIN");
                return;
            }
            for(GrantedAuthority authority : auths) {
                log.info("authority:"+authority.getAuthority());
                if(configAttribute.getAttribute().equals(authority.getAuthority())) {
                    return;
                }
            }
        }
        throw new AccessDeniedException("权限不足");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        // TODO Auto-generated method stub
        return true;
    }

}

请问该怎么解决?

  • 写回答

2条回答 默认 最新

  • 外云 2020-02-17 11:58
    关注

    因为你定义了动态权限的话,就不需要角色继承了,你直接在数据库里把你的权限给改一下,比如说你的ROLE_dba 在数据库里 rid 1 mid 1 rid 1 mid 2这种 给ROLE_dba 俩个权限

    评论

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?