假设我有一个User
实体,其ManyToMany
实体映射到UserGroup
。如果我为两个实体创建存储库并获取URI /users/1
,我会得到这样的响应:
{
"enabled" : true,
"password" : "xxxxxx",
"username" : "xxxxxx",
"credentialsNonExpired" : true,
"accountNonLocked" : true,
"accountNonExpired" : true,
"_links" : {
"self" : {
"href" : "http://127.0.0.1:45950/users/1"
},
"user" : {
"href" : "http://127.0.0.1:45950/users/1"
},
"userGroups" : {
"href" : "http://127.0.0.1:45950/users/1/userGroups"
}
}
}
此处的userGroups链接非常有用。
我可以使用UserGroup
端点列出所有/userGroups
。
我想使用不同的/userGroups
表达式来保护/users/1/userGroups
端点和spring-security
端点。
在此处使用引用:http://docs.spring.io/spring-data/rest/docs/current/reference/html/#security我了解如何保护第一个端点:
public interface UserGroupRepository extends PagingAndSortingRepository<UserGroup, Long> {
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Override
Iterable<T> findAll();
}
但是如何保护第二个端点?这可能是目前的吗?是否有一些工作计划在这样的功能。我很想做出贡献。
答案 0 :(得分:1)
我也遇到过这个问题,但没有找到任何使用Spring安全注释的解决方案。作为一种解决方法,我添加了以下内容:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// Whatever config you already have.
.authorizeRequests()
.antMatchers("/users/*/userGroups").hasRole("ADMIN");
}
我对WebSecurityConfigurerAdapter
的实施。虽然这有效,但它重复了保护存储库时所做的工作,并且在添加新存储库时很容易忘记添加java配置和注释。
答案 1 :(得分:0)
我意识到这个问题已有四年了,但是这个问题一直困扰着我,我终于找到了行之有效的方法。
从本质上说,问题在于Spring HATEOAS没有真正的安全控制;虽然您可以使用适当的方法级安全注释配置存储库以防止通过REST API进行访问,但是您不能阻止HATEAOS表示模型汇编器对它可以看到的任何对象进行处理。
我发现的解决方案是为RepresentationModelProcessor
公开一个EntityModel<DomainObject>
bean。就您而言,这看起来像是
@Configuration
public class SecureHateoasConfig {
public static class UserGroupProcessor implements RepresentationModelProcessor<EntityModel<UserGroup>> {
@Override
public EntityModel<UserGroup> process(EntityModel<UserGroup> model) {
if(SecurityContextHolder.getContext()
.getAuthentication()
.getAuthorities()
.stream()
.map(GrantedAuthority::getAuthority)
.anyMatch("ROLE_ADMIN"::equals)) {
return model;
} else {
return null;
}
}
}
@Bean
public UserGroupProcessor userGroupProcessor() {
return new UserGroupProcessor();
}
}
用null
替换的对象似乎在正常处理后被过滤掉了,因此嵌入式实体根本不包括与过滤器不匹配的对象!
如果只进行基于角色的安全性,可能有一种更简单的方法来过滤链接,但是恐怕我不知道...
当然,可以扩展此范围,因为您的安全对象处理器不仅需要应用于EntityModel<UserGroup>
!在我的情况下,我有一个接口,我所有的安全域对象实现都可以用来制定安全性决策,因此只需要一个RepresentationModelProcessor
实现/ bean。