确保AUTHENTICATED用户被授权访问资源的最佳实践 - Spring mvc,Spring Security,Hibernate

Hur*_*ane 5 acl hibernate spring-mvc spring-security

我们有一个spring mvc rest api,利用spring security和hibernate到MySql db.

我们配置了一些角色.例如:

标准用户:ROLEA

超级用户:ROLEB

目前,为了确保经过身份验证的用户有权访问/更新某个资源,我们执行以下操作:

确定当前经过身份验证的用户:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String activeLogin = authentication.getName();
Run Code Online (Sandbox Code Playgroud)

确定与他们尝试访问的实体关联的登录信息:

String loginAssociatedToRequestedEntity = fooService.getEntityA(EntityAId).getEntityB().getEntityC().getLogin();
Run Code Online (Sandbox Code Playgroud)

将与给定资源关联的用户与活动登录进行比较:

if (!loginAssociatedToRequestedEntity.equals(activeLogin)) { 
throw new ForbiddenAccessException();
}
Run Code Online (Sandbox Code Playgroud)

我有很多问题,其中一些问题包括:

  • 非常浪费......每个实体都必须保湿/填充.如果要访问的实体远离具有登录名的表,则这可能比上面的示例更糟糕.
  • 看起来像代码味(Demeter法).
  • 可能会有可能更新多个实体的请求.可能必须重复对上述的类似检查.

我考虑过以下可能的选项:

Spring ACLs

Apache shiro

所以我的问题是,是否有最佳做法是确保经过身份验证的用户有权访问某个资源,即阻止他们访问同一角色的其他用户的资源.

如果你能指出一个非常值得赞赏的具体例子(github).

TIA.

fsp*_*irn 7

虽然角色成员资格检查在某种程度上是反模式(最好是对权限或活动进行编码),但它们通常用于服务级别访问控制(Web请求和方法调用),但根本不适合保护实际的域对象在多租户设置中,例如,以防止用户访问具有相同角色的另一用户的资源.

检查经过身份验证的登录是否与特定域对象关联的方法是可行的,但是它很麻烦,将应用程序数据模型与安全数据模型耦合和/或污染,并且您认为这不是最佳做法.

您已经确定了一些选项:

Apache Shiro提供了一致且易于使用的API,支持域对象访问控制,但您负责提供后端"领域",这意味着您可能必须实现自己的数据存储和/或DAO.

Spring Security ACL是Spring的安全域对象访问控制范例.它将安全数据模型与应用程序数据模型分离.访问控制列表通过添加或查找ACL条目,可以轻松授予或检查域对象的访问权限,但如果要有效地查找用户有权访问的所有域对象,则可能需要编写自己的DAO(例如,列表中的对象或撤消对它们的访问权限).此外,有责任维护ACL,因为:

Spring Security不提供任何特殊集成来自动创建,更新或删除ACL,作为DAO或存储库操作的一部分.相反,您需要为各个域对象编写代码[...].值得考虑在服务层使用AOP来自动将ACL信息与服务层操作集成.

- Spring Security 4.0参考

最后,如果默认API与您的应用程序模型不兼容,您必须自定义ACL实现(例如,如果您的域对象没有公共getId()或不使用兼容的ID long)

如果您没有与Spring或Shiro结婚以提供域对象访问控制,那么还有另一种选择:

OACC是一个开源Java安全框架(披露:我是维护者和共同作者),它提供了丰富的API来强制管理您的授权需求.OACC是一个完整的访问控制框架,具有丰富的API,无需任何DIY实现即可实现细粒度授权的编程和动态建模.它为其安全模型提供了完全实现的RDBMS支持的数据存储,API在后台为您管理.

OACC的安全模型是基于权限的:它实质上管理资源之间的权限.资源代表安全域对象及其上的参与者(即主题).它还提供了有效的查询方法,可以通过权限查找资源,而无需先加载所有资源,然后过滤掉未经授权的资源.这些方法是对称的,因为您可以找到指定资源具有特定权限集的资源,以及对指定资源具有特定权限集的资源.

将OACC片段与下面的权限进行比较,使用Spring Security ACL参考中示例代码:

// get the resource representing the principal that we want to grant permissions to
User accessorUser = Users.findByName("Samantha");
Resource accessorResource = Resources.getInstance(accessorUser.getId());

// get the resource representing the object that we want to grant permissions to
Resource accessedResource = Resources.getInstance(Foos.findById(44).getId());

// Now grant some permissions
Permission permission = ResourcePermissions.getInstance("ADMINISTER");
oacc.grantResourcePermissions(accessorResource, 
                              accessedResource,
                              permission);
Run Code Online (Sandbox Code Playgroud)

要查看授权,您可以致电

oacc.assertResourcePermissions(accessorResource, accessedResource, permission);
Run Code Online (Sandbox Code Playgroud)

或检查的返回值

oacc.hasResourcePermissions(accessorResource, accessedResource, permission);
Run Code Online (Sandbox Code Playgroud)

OACC的另一个新颖特性是创建权限,它不仅可以控制主体可以创建的资源类型,还可以在创建新资源准确定义它们将获得哪些权限- 定义一次,权限自动分配给资源创建者,无需显式API调用.

总之,OACC是专门针对您的经过身份验证的细粒度授权的用例而开发的.