@胡海龙 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 俩个权限

    评论

报告相同问题?

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看