7.9. 导入实施策略
在实施用户存储提供程序时,您可以采用另外一种策略。您可以在 Red Hat build of Keycloak 内置用户数据库中本地创建用户,并将外部存储中的属性复制到这个本地副本中,而不是使用用户联邦存储。这种方法有很多优点。
- 红帽构建的 Keycloak 基本上成为外部存储的持久性用户缓存。导入用户后,您将不会再达到外部存储,从而退出它。
- 如果您要作为官方用户存储并弃用旧的外部存储红帽构建的 Keycloak,您可以慢慢地迁移应用程序以使用红帽构建的 Keycloak。当所有应用都已迁移后,取消链接导入的用户,然后停用旧的外部存储。
使用导入策略时有一些明显的缺点:
- 第一次查找用户需要多次更新红帽构建的 Keycloak 数据库。这可能会给负载造成大量性能损失,并在红帽构建的 Keycloak 数据库中造成大量压力。用户联合存储方法将仅存储额外的数据,并且可能永远不会根据外部存储的功能使用。
- 通过导入方法,您必须保留本地红帽构建的 Keycloak 存储和外部存储同步。用户存储 SPI 具有您可以实现支持同步的功能接口,但可能会快速变得困难且出现问题。
若要实施导入策略,只需先检查以查看用户是否已在本地导入。如果返回本地用户,如果没有在本地创建用户,并从外部存储导入数据。您还可以代理本地用户,以便自动同步大多数更改。
这将是稍微的,但我们可以扩展 PropertyFileUserStorageProvider 来采用这种方法。首先修改 createAdapter () 方法。
PropertyFileUserStorageProvider
在这个方法中,我们调用 UserStoragePrivateUtil.userLocalStorage (session) 方法来获取对本地红帽构建的 Keycloak 用户存储的引用。我们可以看到用户是否存储在本地,如果没有,我们将在本地添加。不要设置本地用户的 id。让红帽构建 Keycloak 会自动生成 id。另请注意,我们调用 UserModel.setFederationLink (),并传递我们供应商的 ComponentModel 的 ID。这会设置供应商和导入的用户之间的链接。
删除用户存储提供程序时,也会删除它导入的任何用户。这是调用 UserModel.setFederationLink () 的一个目的。
需要注意的是,如果本地用户链接了某一本地用户,您的存储提供程序仍将被委派为从 CredentialInputValidator 和 CredentialInputUpdater 接口实现的方法。从验证或更新返回 false 时,只有红帽构建 Keycloak 以查看它是否可以使用本地存储验证或更新。
另请注意,我们使用 org.keycloak.models.utils.UserModelDelegate 类代理本地用户。此类是 UserModel 的实施。每个方法仅委托给 用户模型,用它实例化。我们覆盖此委派类的 setUsername () 方法,以与属性文件自动同步。对于供应商,您可以使用它 截获 本地 UserModel 上的其他方法,以执行与外部存储同步。例如,get 方法可以确保本地存储处于同步状态。设置方法使外部存储与本地存储保持同步。需要注意的是,getId () 方法应始终返回您在本地创建用户时自动生成的 id。您不应该返回联邦 id,如其它非导入示例所示。
如果您的供应商实现 UserRegistrationProvider 接口,则您的 removeUser () 方法不需要从本地存储中删除该用户。运行时会自动执行此操作。另请注意,在从本地存储中删除 removeUser () 之前,会先调用 removeUser ()。
7.9.1. ImportedUserValidation 接口 复制链接链接已复制到粘贴板!
如果您记得在本章的前面部分,我们讨论如何查询用户工作。如果找到了用户,则会首先查询本地存储,然后查询结束。这是以上实施的一个问题,因为我们希望代理本地 UserModel,以便我们可以使用户名保持同步。用户存储 SPI 具有回调,每当从本地数据库加载链接的本地用户时。
每当加载链接的本地用户时,如果用户存储类实施此接口,则调用 validate () 方法。您可以在此处代理作为参数传递的本地用户并返回它。这将使用新的 UserModel。您还可以选择检查来查看用户是否存在于外部存储中。如果 validate () 返回 null,则本地用户将从数据库中删除。
7.9.2. ImportSynchronization 接口 复制链接链接已复制到粘贴板!
使用导入策略时,您可以看到本地用户复制可以与外部存储不同步。例如,一个用户已从外部存储中删除。User Storage SPI 有一个额外的接口,您可以实现处理这个接口 org.keycloak.storage.user.ImportSynchronization :
这个接口由供应商工厂实现。当此接口由供应商工厂实现后,供应商的管理控制台管理页面会显示其他选项。您可以点击按钮来手动强制同步。这会调用 ImportSynchronization.sync () 方法。另外,会显示额外的配置选项,供您自动调度同步。自动同步调用 syncSince () 方法。