使用Spring(Java)

时间:2016-12-29 21:48:56

标签: java spring rest spring-data-jpa

我正在寻找RESTful Web服务和后端数据模型的多租户权限模型的示例。我使用Spring在Java中构建了OAUTH AS和RESTful Web服务。大部分后端都已完成,但现在我正在构建安全性。我需要的是用户对不同对象拥有不同权限的能力。为了论证,让我们说有些公司包含帐户。经过身份验证的用户可以拥有以下任何权限:

  • 超级用户 - 对所有内容的完全权利
  • 公司管理员权利 - 该公司内一家或多家公司和帐户的各种财产的权利。
  • 帐户权利 - 对公司中一个或多个帐户的权利。

例如,Alice可以是超级管理员。 Bob可以拥有ACME-USER1的帐户权限,但拥有INITECH的公司管理员权限以及该公司的所有帐户。 Bill只是拥有超过INITECH-USER2的USER权限的最终用户。

最初这个概念将应用于REST控制器。我的网络服务看起来像这样:

  • POST / company - >创建公司 - >超级用户
  • GET / company / {id} - >获得公司 - >该公司的超级用户和公司管理员
  • POST / company / {id} / account - >在公司创建帐户 - >该公司的超级用户和公司管理员
  • GET / company / {id} / account / {acctid} - >获取一个帐户 - >超级用户,公司管理员和该用户

这个概念也将扩展到数据模型。一家公司说具有以下属性并需要以下权限来修改每个属性:

  • 名称 - >超级管理员
  • contact_name - >公司管理员
  • contact_email - >公司管理员
  • max_accounts - 超级管理员

用户模型如下所示:

  • 名称 - >用户
  • 电子邮件 - >用户
  • 已启用 - >公司管理员
  • quota - >超级管理员

我创建了OAUTH AS授予的权限,例如:

  • ROLE_SUPERADMIN
  • ROLE_COMPANYADMIN-ACME
  • ROLE_COMPANYADMIN-Initech的
  • ROLE_USERADMIN-ACME-USER1
  • ROLE_USERADMIN-ACME-USER2

由于角色不是静态的,我不相信我能够在Java中使用@Secured或@PreAuthorize等注释。我编写了一个方法,将Principal,company和user作为参数,然后生成所需的角色并检查用户是否拥有它。我不确定这是不是最好的做法,还是有一个" Spring-y"这样做的方式。如上所述,我也希望这适用于我的数据模型。我不希望必须使用自己的REST控制器将实体拆分为多个数据传输对象,并在其中评估权限。

我还阅读http://www.baeldung.com/role-and-privilege-for-spring-security-registration,其中包含具有特权的角色。我喜欢这个模型,因为我会创建像CREATE_COMPANY或EDIT_QUOTA这样的细化权限。然后必须将这些应用于特定对象。

任何有关实施此类内容的项目或关于最佳实践的一般想法的任何示例都将受到赞赏。

1 个答案:

答案 0 :(得分:3)

在Spring SpEL中,您可以在上下文Spring Expression Language (SpEL). Bean references.中收到任何bean的引用。

在这种情况下,您可以使用@PreAuthorize注释。例如:

@Component("accessChecker")
public class AccessChecker {
  public boolean hasAccessToCompany(Long companyId) {
    return checkAccessRightsHere(SecurityContextHolder.getContext().getAuthentication(), companyId);
  }
}  

@Controller
public class CompanyController {
   @RequestMapping("/company/{companyId}")
   @PreAuthorize("@accessChecker.hasAccessToCompany(#companyId)")
   public CompanyDto getCompany(@PathVariable("comapanyId") Long companyId) {

   }
}