我应该如何根据 Spring 中的用户角色将端点设计为 return 不同的模型

How should I design endpoint to return different models depending on User role in Spring

所以假设我有 2 个模型 classes - User 和 Presentation,它们看起来像这样:

@Entity
public class Presentation {

    @Id
    private Long id;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

@Entity
public class User implements UserDetails {

    @Id
    private Long id;

    private String username;

    private String name;

    private String surname;

    private String password;

    @Enumerated(EnumType.STRING)
    private Role role;
}

如您所见,我在 Presentation class 中为用户创建了一个单向映射。我的端点看起来像这样:

@RestController
public class PresentationController {
    
    @GetMapping("/{presentationId}")
    public PresentationDTO getPresentation(@PathVariable Long presentationId) {
        return presentationService.getPresentationById(presentationId);
    }

    @GetMapping
    public List<PresentationDTO> getAllPresentations() {
        return presentationService.getAllPresentations();
    }
}

现在回答我的问题 - 如何将 getAllPresentations() 更改为 return 角色为“user”的用户拥有的演示文稿,以及 return 角色为“admin”的用户的所有演示文稿?我知道我可以创建一个具有不同映射(如 /admin/presentations)的单独端点并添加 @PreAuthorize(hasRole("admin")),但这是棘手的部分。 对于 getAllPresentations() 端点,每个经过身份验证的人都应该获取他自己的演示文稿,我怎么知道我必须为哪个用户 return 他的演示文稿?也许我可以获得用户名作为参数,但这可能很危险,因为他可以提交他想要的任何用户名并获得该用户的演示文稿。我不太了解 Spring 安全性,我什至不知道要问 google 正确的问题以获得答案,所以我被困住了...... 任何帮助将不胜感激,谢谢!

您不必将用户名传递给您的控制器方法。当前经过身份验证的用户可通过 Spring.The 中的多种不同机制获得,检索当前经过身份验证的主体的最简单方法是通过对 SecurityContextHolder 的静态调用,如下所示:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = authentication.getName();

因此您可以重构服务 class 中的方法 getAllPresentations() 以接受 username 作为参数,然后您可以通过传递的 username 和 [=21 加载用户=] 该用户的演示文稿。

做你想做的事情的一种方法是使用 @PostFilter 注释来过滤已验证用户拥有的 List<Presentation> 或者如果已验证用户具有这样的角色 ADMIN

@GetMapping
@PostFilter("filterObject.user.username == authentication.principal.username or hasRole('ADMIN')")
public List<PresentationDTO> getAllPresentations() {
    return presentationService.getAllPresentations();
}