Spring Security 的 ACL 配置问题
Posted
技术标签:
【中文标题】Spring Security 的 ACL 配置问题【英文标题】:ACL configuration problems with Spring Security 【发布时间】: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 做同样的事情,如果这是我所有问题的原因,我不知道。
【问题讨论】:
【参考方案1】:这个问题是针对@secure 注释的,但我终于解决了这个问题,为使用@Pre 和@Post 注释做一个类配置,我在这个question 的答案中发布了一个配置java 类。
【讨论】:
以上是关于Spring Security 的 ACL 配置问题的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security 中的访问总是被拒绝 - DenyAllPermissionEvaluator