【问题标题】:ACL configuration problems with Spring SecuritySpring Security 的 ACL 配置问题
【发布时间】:2015-11-19 11:32:56
【问题描述】:

我是 Spring 世界的新手,我正在使用 Spring Boot 1.2.5 和 Spring Security 3.1.2。由于我的项目要求,我需要配置 ACL 安全模型。我有以下 java 类配置:

@Configuration
public class ACLConfig {

    @Autowired
    DataSource dataSource;


    @Bean
    JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    EhCacheBasedAclCache aclCache() {
        EhCacheFactoryBean factoryBean = new EhCacheFactoryBean();
        EhCacheManagerFactoryBean cacheManager = new   EhCacheManagerFactoryBean();
        cacheManager.setAcceptExisting(true);
      cacheManager.setCacheManagerName(CacheManager.getInstance().getName());
        cacheManager.afterPropertiesSet();

        factoryBean.setName("aclCache");
        factoryBean.setCacheManager(cacheManager.getObject());
        factoryBean.setMaxBytesLocalHeap("16M");
        factoryBean.setMaxEntriesLocalHeap(0L);
        factoryBean.afterPropertiesSet();
        return new EhCacheBasedAclCache(factoryBean.getObject());
    }

    @Bean
    LookupStrategy lookupStrategy() {
        return new BasicLookupStrategy(dataSource, aclCache(),  aclAuthorizationStrategy(), new ConsoleAuditLogger());
    }

    @Bean
    AclAuthorizationStrategy aclAuthorizationStrategy() {
        return new AclAuthorizationStrategyImpl(new  SimpleGrantedAuthority("ROLE_SUPER_ADMIN"),
        new SimpleGrantedAuthority("ROLE_SUPER_ADMIN"),
        new SimpleGrantedAuthority("ROLE_SUPER_ADMIN"));
    }

    @Bean
    JdbcMutableAclService aclService() {
        JdbcMutableAclService service = new     JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());
        service.setClassIdentityQuery("select currval(pg_get_serial_sequence('acl_class', 'id'))");
        service.setSidIdentityQuery("select currval(pg_get_serial_sequence('acl_sid', 'id'))");
        return service;
    }

    @Bean
    AclEntryVoter aclDeleteVoter()
    {
        AclEntryVoter voter = new   AclEntryVoter(aclService(),"ACL_NOMCITY_DELETE", new Permission[]  {BasePermission.DELETE});
        voter.setProcessDomainObjectClass(NomCity.class);
        return voter;
    }

    @Bean
    AclEntryVoter aclUpdateVoter()
    {
        return new AclEntryVoter(aclService(),"ACL_NOMCITY_UPDATE", new   Permission[]{BasePermission.ADMINISTRATION});
    }

    @Bean
    AclEntryVoter aclReadVoter()
    {
        return new AclEntryVoter(aclService(),"ACL_NOMCITY_READ", new   Permission[]{BasePermission.READ});
    }

    @Bean
    AccessDecisionManager accessDecisionManager (){

        List<AccessDecisionVoter<? extends Object>> list = new ArrayList<>();
        list.add(aclDeleteVoter());
        list.add(aclReadVoter());
        list.add(aclUpdateVoter());
        return new AffirmativeBased(list);
    }

}

我有以下 RestController 的方法,它使用前面定义的 ACL:

@RequestMapping(value = "/nomCitys",
        method = RequestMethod.POST,
        produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional
@Secured({"ROLE_ADMIN","ROLE_USER"})
public ResponseEntity<NomCity> create(@Valid @RequestBody NomCity nomCity) throws URISyntaxException {

    NomCity result = nomCityRepository.save(nomCity);

    User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    ObjectIdentity oi = new ObjectIdentityImpl(NomCity.class,result.hashCode());
    MutableAcl acl = mutableAclService.createAcl(oi);

    acl.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid("ROLE_ADMIN"), true);
    acl.insertAce(1, BasePermission.DELETE, new PrincipalSid(user.getUsername()), true); 
    acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER"), true);

    mutableAclService.updateAcl(acl);

    return ResponseEntity.created(new URI("/api/nomCitys/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert("nomCity", result.getId().toString()))
            .body(result);
}

当我创建一个新城市时,也会创建以下 ACL 条目:

  • 具有 ROLE_ADMIN 角色的用户具有管理员权限。
  • 创建城市的用户拥有删除权限。
  • 具有 ROLE_USER 角色的用户可以读取城市。

以下方法为删除方法:

@RequestMapping(value = "/nomCitys/{id}",
        method = RequestMethod.DELETE,
        produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional
@Secured("ACL_NOMCITY_DELETE")
public ResponseEntity<Void> delete(@PathVariable Long id) {

    nomCityRepository.delete(id);

    ObjectIdentity oid = new ObjectIdentityImpl(NomCity.class,id);
    mutableAclService.deleteAcl(oid, true);

    return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert("nomCity", id.toString())).build();
}

当我创建一个新城市时,一切正常,ACL 条目被创建并存储在数据库中,但是当我去删除一个城市时,我得到一个 403,尽管我使用创建城市的用户登录,查看一些页面我看到了以下 xml 条目:

<security:global-method-security
  secured-annotations="enabled" access-decision-manager  ref="customAccessDecisionManager" />

我想它注册了 AccessDecisionManager,但我不知道如何使用 Java Config 做同样的事情,如果这是我所有问题的原因,我不知道。

【问题讨论】:

    标签: java spring spring-security


    【解决方案1】:

    这个问题是针对@secure 注释的,但我终于解决了这个问题,为使用@Pre 和@Post 注释做一个类配置,我在这个question 的答案中发布了一个配置java 类。

    【讨论】:

      猜你喜欢
      • 2018-02-02
      • 2016-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-14
      • 2016-11-26
      • 1970-01-01
      相关资源
      最近更新 更多