资源角色
资源角色赋予用户对系统中特定对象和操作的权限:对实体的 CRUD 操作权限、实体属性权限、UI 界面权限等。
没有资源角色的用户没有任何权限,无法访问应用程序的数据和 UI。 |
创建资源角色
可以在设计时使用带注解的 Java 接口(参考 Studio 角色设计器)创建资源角色,或者在运行时用 Administration(管理) → Resource roles(资源角色) 界面创建。
每个角色有一个用户友好的名称和一个编码。给用户分配角色时使用编码,因此如果已经有用户分配了某个角色,不要再次修改此角色的编码了。
定义设计时角色示例:
@ResourceRole( (1)
name = "Full Access", (2)
code = "system-full-access") (3)
public interface FullAccessRole {
// ...
void fullAccess(); (4)
}
1 | @ResourceRole 注解表示这个接口定义了资源角色。 |
2 | 用户友好的角色名。 |
3 | 角色的编码。 |
4 | 接口可以有一个或多个方法用来定义策略注解(见下文)。不同的方法只是用来对相关的策略进行分组。方法名没有限制,当角色在 UI 展示时,方法名作为 Policy group(策略组) 展示。 |
资源策略
资源角色通过指定 资源策略 定义许可权限。资源策略由一个资源和对该资源的访问权限组成。
实体策略
实体策略指定对实体的 CRUD 操作权限。
在设计时角色中,实体策略使用 @EntityPolicy
注解定义,示例:
@EntityPolicy(
entityClass = Customer.class,
actions = {EntityPolicyAction.READ,
EntityPolicyAction.CREATE,
EntityPolicyAction.UPDATE})
void customer();
用 entityClass
参数指定实体。如需定义所有实体的策略,请将 entityName
参数设置为 *
。
actions
参数设置许可的 CRUD 操作。如需请用所有操作,设置为 EntityPolicyAction.ALL
值。
实体属性策略
实体属性策略指定对实体属性的操作权限。
在设计时角色中,实体属性策略使用 @EntityAttributePolicy
注解定义,示例:
@EntityAttributePolicy(
entityClass = Customer.class,
attributes = {"name", "region", "details"},
action = EntityAttributePolicyAction.MODIFY)
void customer();
用 entityClass
参数指定实体。如需定义所有实体的策略,请将 entityName
参数设置为 *
。
用 attributes
参数指定实体属性名称。如需定义所有实体属性的策略,设置为 *
。
action
参数设置许可的级别:“view(查看)” 或 “modify(修改)”。“modify” 级别包含 “view”。
界面策略
界面策略指定 UI 界面的许可权限。
在设计时角色中,界面策略使用 @ScreenPolicy
注解定义,示例:
@ScreenPolicy(
screenIds = {"sample_Customer.browse", "sample_Customer.edit"})
void customer();
screenIds
参数指定许可的 UI 界面 id。如需启用全部界面,设置为 *
。
菜单策略
菜单策略指定 UI 主菜单项的许可权限。
在设计时角色中,菜单策略使用 @MenuPolicy
注解定义,示例:
@MenuPolicy(
menuIds = {"sample_Customer.browse"})
void customer();
menuIds
参数指定许可的菜单项 id。如需启用全部菜单项,设置为 *
。
特殊策略
特殊策略用于定义任何其他功能的权限。
框架使用特定权限来限制对各种机制的访问。例如,通用 REST API 定义了 rest.enabled
策略,因此用户必须拥有此权限才能使用 REST API 接口与应用程序交互。
你也可以使用特定策略来限制对应用程序功能的访问。以下是这种访问控制的示例。
在设计时角色中,特殊策略使用 @SpecificPolicy
注解定义,示例:
@SpecificPolicy(
resources = {"customer.notify"})
void customer();
使用框架提供的 AccessManager
和 SpecificOperationAccessContext
类在应用程序代码中检查策略:
@Autowired
private AccessManager accessManager;
public void notifyCustomer(Customer customer) {
SpecificOperationAccessContext accessContext =
new SpecificOperationAccessContext("customer.notify");
accessManager.applyRegisteredConstraints(accessContext);
if (accessContext.isPermitted()) {
// do notify
}
}
参阅 访问约束 部分了解有关检查权限的更多内容。
如需启用所有的特殊策略,在 @SpecificPolicy.resources
注解属性中使用 *
值。
角色粒度
一个资源角色可以有任意数量的策略,并且一个用户可以有任意数量的角色。因此,可以设计具有不同粒度级别的角色:
-
细粒度的角色定义了对紧密相关资源(如实体、实体 UI 界面和菜单项)的权限。例如,“对 Customer 的完全访问权限”、“可以创建和更新 Orders”。通常会给用户分配几个这样的角色。
-
粗粒度角色定义了特定工作所需的所有权限,例如,“销售人员”。这样的角色本身可以定义所有权限或从子角色继承,因此可以将粗粒度角色作为细粒度角色的聚合。
我们建议在设计时创建细粒度角色,仅使用运行时功能将它们组合成不同的粗粒度角色,以便能更简单地给用户分配角色,并支持对安全模型临时进行调整。
示例
下面是设计时资源角色的完整示例,启用了对下列实体和它们 UI 的有限访问权限:
@ResourceRole(
name = "Customers: non-confidential info only, cannot delete",
code = "customer-nonconfidential-access")
public interface CustomerNonConfidentialAccessRole {
@EntityPolicy(
entityClass = Customer.class,
actions = {EntityPolicyAction.READ,
EntityPolicyAction.CREATE,
EntityPolicyAction.UPDATE})
@EntityAttributePolicy(
entityClass = Customer.class,
attributes = {"name", "region", "details"},
action = EntityAttributePolicyAction.MODIFY)
@ScreenPolicy(
screenIds = {"sample_Customer.browse", "sample_Customer.edit"})
@MenuPolicy(
menuIds = {"sample_Customer.browse"})
void customer();
@EntityPolicy(
entityClass = CustomerDetail.class,
actions = EntityPolicyAction.ALL)
@EntityAttributePolicy(
entityClass = CustomerDetail.class,
attributes = {"content"},
action = EntityAttributePolicyAction.MODIFY)
@ScreenPolicy(
screenIds = {"sample_CustomerDetail.edit"})
void customerDetail();
@MenuPolicy(
menuIds = {"application"})
void commonMenus();
}