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

Best practice to make sure an AUTHENTICATED user is AUTHORISED to access a resource - Spring mvc, Spring Security, Hibernate

我们有一个 spring mvc rest api,利用 spring 安全和休眠到 MySql 数据库。

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

标准用户:ROLEA

超级用户:ROLEB

目前,为了确保经过身份验证 的用户获得 对access/update 特定资源的授权,我们会这样做:

识别当前认证用户:

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

确定与他们试图访问的实体关联的登录名:

String loginAssociatedToRequestedEntity = fooService.getEntityA(EntityAId).getEntityB().getEntityC().getLogin();

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

if (!loginAssociatedToRequestedEntity.equals(activeLogin)) { 
throw new ForbiddenAccessException();
}

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

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

Spring ACLs

Apache shiro

所以我的问题是,是否有最佳实践来确保 已验证 用户是 授权 以访问特定资源,即停止他们无法访问具有相同角色的另一个用户的资源。

如果您能指出一个具体的例子 (github),我们将不胜感激。

TIA。

您可以使用 Spring Data JPA 将 Spring 安全主体信息添加到您的 SQL 查询中。示例:

https://github.com/spring-projects/spring-data-examples/blob/master/jpa/security/src/main/java/example/springdata/jpa/security/SecureBusinessObjectRepository.java

您还可以使用 PostgreSQL 9.5、Oracle VPD 或 SQL Server 2016 等具有行安全性的数据库

虽然角色成员资格检查有点反模式(最好编写权限或 activity),但它们通常用于服务级别访问控制(Web 请求和方法调用),但是完全不适合保护多租户环境中的实际域对象,例如以防止用户访问同一角色的另一个用户的资源。

您检查经过身份验证的登录是否与特定域对象相关联的方法可行,但它很麻烦,而且 and/or 会用安全数据模型污染您的应用程序数据模型,正如您所怀疑的那样,是不是最佳做法。

您已经确定了一些选项:

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

Spring 安全 ACL 是 Spring 用于保护域对象的访问控制范例。它将安全数据模型与您的应用程序数据模型分离。访问控制列表可以通过添加或查找 ACL 条目轻松授予或检查对域对象的访问权限,但如果你想有效地找到用户有权访问的所有域对象(例如,呈现那些列表中的对象或撤销对它们的访问权限)。此外, 负责维护 ACL,因为:

Spring Security does not provide any special integration to automatically create, update or delete ACLs as part of your DAO or repository operations. Instead, you will need to write code [...] for your individual domain objects. It’s worth considering using AOP on your services layer to automatically integrate the ACL information with your services layer operations.

Spring Security 4.0 reference

最后,如果默认 API 与您的应用程序模型不兼容(例如,如果您的域对象没有 public getId() 或不使用与 long)

兼容的 ID

如果您没有选择 Spring 或 Shiro 来提供域对象访问控制,还有另一种选择:

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

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

将下面授予权限的 OACC 片段与 sample code from the Spring Security ACL reference 进行比较:

// 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);

要检查授权,您可以调用

oacc.assertResourcePermissions(accessorResource, accessedResource, permission);

或检查

的return值
oacc.hasResourcePermissions(accessorResource, accessedResource, permission);

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

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