我的Spring启动应用中有两个实体和两个服务层:User
,Group
以下removeMember
方法位于服务层中:
/*Remove member with id userId from group with id groupId, if username is the admin of that group*/
public void removeMember(long groupId, long userId, String username) {
Group group = loadById(groupId);
validateAdminAccessToGroup(group, username);
User user = userService.loadById(userId);
validateMemberAccessToGroup(group, user.getName());
if (group.isAdmin(user)) {
throw new BadRequestException("Group admin cannot delete himself/herself from the group");
}
group.removeMember(user);
}
private void validateAdminAccessToGroup(Group group, String username) {
User user = userService.loadByName(username);
if (!group.isAdmin(user)) {
throw new AccessDeniedException("User with id " + user.getId() + " was denied to access group with id " + group.getId() + " as an admin");
}
}
private void validateMemberAccessToGroup(Group group, String username) {
User user = userService.loadByName(username);
if (!group.isMember(user)) {
throw new AccessDeniedException("User with id " + user.getId() + " was denied to access group with id " + group.getId());
}
}
如您所见,只有组的管理员才能从该组中删除成员。
validateAdminAccessToGroup
验证用户是否具有访问组的管理员权限,否则会通过错误。 validateMemberAccessToGroup
验证用户是组的成员。
我们应该在方法内进行访问检查吗?或使用@PreAuthorize注释?我们可以说这是一个贯穿各领域的问题吗?
答案 0 :(得分:0)
在我看来,最好处理checkAccessToGroup
模型对象中的User
,而不是既不传递User
,GroupId
也不传递AccessLevel
,只是处理它在模型内部,将这些值设置为对象成员变量。
然后在Controller层的User
实例上调用它。如果您在Service层中调用它,当一个Controller在Service中使用多个方法时,您需要在Service方法中重复调用它,并且最终会将Access Checking部分与Service本身紧密耦合,这将减少服务的可重用性。
答案 1 :(得分:0)
我建议你使用spring security的PreAuthorize类。 Here是一个小例子。您的代码可以从PermissionEvaluator实现中调用,该实现将由spring内部类调用。
因为您需要基于实体/记录的访问,所以您可以实现覆盖hasPermission方法,该方法将以下参数作为输入身份验证(登录用户详细信息),targetId(groupId),targetType(组),权限(删除)。
您需要在控制器/服务方法之上使用以下注释。
@PreAuthorize(" hasPermission(#groupId,' groupd','删除')")
这会将所有不同服务的所有授权逻辑移动到一个类中。