Spring Security-基于所有权的访问

时间:2019-07-03 13:24:48

标签: java spring spring-boot security spring-security

假设通过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之类的东西。 -基于访问控制

还有其他想法吗?有人对资源所有权检查有一个好主意或示例吗?

3 个答案:

答案 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());
    }
}

有关更全面的教程,请查看tutorial找到的0x1C1B链接

答案 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