假设通过Java 8和Spring Boot 2,我有一个最小的RESTful控制器,如下所示...
@RestController
class MyController {
@Autowired
private PostService service;
@GetMapping
public Post get() {
return service.getLatest();
}
}
我已经使用Spring Security模块成功保护了此路由。现在,我只允许资源所有者访问该资源。对于资源所有者,我的意思是创建者或说简单:
Post myPost = new Post();
...
myPost.getCreator().equals(currentUser); // Should be true when access is granted
我发现了很多有关基于角色的访问的信息,但是几乎没有任何东西可以用来检查所有权...当然,我可以在控制器中放置一个if语句并抛出异常,但是我打算使用类似Spring的 Expression之类的东西。 -基于访问控制。
还有其他想法吗?有人对资源所有权检查有一个好主意或示例吗?
答案 0 :(得分:0)
在基于角色的方法中,角色是预先定义的,与响应/资源无关。但是在您的情况下,我们需要首先获取资源以检查用户是否为所有者。我们无法事先决定。
假设,如果用户具有ROLE_ADMIN,则他将成为所有资源的管理员。
在您的情况下,所有权完全取决于资源。我建议您进行手动if
检查。如果Post
对象很重,则可以维护一个单独的表,其中只有两列resource_id和owner。那么如果所有者匹配,则可以稍后再获取资源,否则可以向用户发送403禁止响应。
答案 1 :(得分:0)
对于简单的get操作,您只需返回链接到当前登录用户的帖子
@GetMapping
public Post getPost(Authentication authentication) {
return service.getPostByUser(authentication.getName());
}
要更新现有帖子,可以在PreAuthorize中检查创建者是否是登录用户。 authentication.getName()在我的示例中返回一封电子邮件
@PutMapping
@PreAuthorize("#post.getCreator() == authentication.getName()")
public void update(@RequestBody Post post, Authentication authentication) {
service.updatePost(post);
}
@Component方法的基本示例
@Autowired
private CreatorCheck creatorCheck;
@PutMapping
@PreAuthorize("@creatorChecker.check(#post,authentication)")
public void update(@RequestBody Post post, Authentication authentication) {
service.updatePost(post);
}
和组件。可以扩展以检索原始的帖子并检查该创建者。
@Component
public class CreatorCheck {
public boolean check(Post post, Authentication authentication) {
return post.getCreator().equals(authentication.getName());
}
}
答案 2 :(得分:0)
Here是一个小指南,可以帮助我解决此问题。 如果您使用CRUD存储库:
@Override
@PreAuthorize("#entity.id == authentication.principal.id")
<S extends User> S save(S entity);
对于资源所有者和管理员:
@PreAuthorize("#entity.id == authentication.principal.id || hasAuthority('ADMIN')")
因此,只需在子CRUD存储库中覆盖所需的方法即可。它适用于@RepositoryRestResource