Java keydepose用户存储SPI实现

Java keydepose用户存储SPI实现,java,keycloak,keycloak-services,Java,Keycloak,Keycloak Services,我正在尝试实现一个自定义KeyClock验证器SPI,用于针对外部数据源进行身份验证。SpringBootREST服务也可用,我也可以使用它 我试图解决的用例是 用户将看到KeyClope登录屏幕。根据外部数据源验证Onsubmission用户 从外部数据源检索一些属性,将其映射到KeyClope的id和访问令牌 还设置了同一用户同时多次登录的用户限制条件 我在想,可以通过检索KeyClope数据源中可用的用户会话信息来解决这个问题。如果我使用外部数据源,KeyClope是否仍然维护会话信息 我

我正在尝试实现一个自定义KeyClock验证器SPI,用于针对外部数据源进行身份验证。SpringBootREST服务也可用,我也可以使用它

我试图解决的用例是

用户将看到KeyClope登录屏幕。根据外部数据源验证Onsubmission用户

从外部数据源检索一些属性,将其映射到KeyClope的id和访问令牌

还设置了同一用户同时多次登录的用户限制条件

我在想,可以通过检索KeyClope数据源中可用的用户会话信息来解决这个问题。如果我使用外部数据源,KeyClope是否仍然维护会话信息

我遵循了官方指南的第8.3节,这与我所需要的非常相似

现在我跳过了,并按照第11节开始,似乎也更合适

我所做的是从实现自定义验证器开始,SPI认为这不是正确的方法,现在实现了UserStorageProvider

/***
 * From UserLookupProvider
 */
public UserModel getUserById(String id, RealmModel realm) {
    System.out.println("ID: " + id + ":REALM:" + realm);
    StorageId storageId = new StorageId(id);
    /**
     * StorageId.getExternalId() method is invoked to obtain 
     * the username embeded in the id parameter
     */
    String username = storageId.getExternalId();
    System.out.println("Name:" + username);
    return getUserByUsername(username, realm);
}

/***
 * From UserLookupProvider
 * This method is invoked by the Keycloak login page when a user logs in
 */
public UserModel getUserByUsername(String username, RealmModel realm) {
    System.out.println("USERNAME: " + username + ":REALM:" + realm);
    UserModel userModel = loadedUsers.get(username);
    if (userModel == null) {
        String password = properties.getProperty(username);
        if (password != null) {
            userModel = createUserModel(realm, username);
            System.out.println("New UserModel:");
            System.out.println(userModel.toString());
            loadedUsers.put(username, userModel);
        }
    }
    return userModel;
}

protected UserModel createUserModel(RealmModel realm, String username) {
    return new AbstractUserAdapter(session, realm, model) {
        @Override
        public String getUsername() {
            return username;
        }
    };
}
跟着医生

我们的提供者实现的类文件应该放在jar中。您还必须在META-INF/services/org.keydrope.storage.UserStorageProviderFactory文件中声明提供者工厂类

这里的问题是:我创建的jar在META-INF文件夹中并没有服务目录,我需要手动创建并添加它吗

org.keydape.examples.federation.properties.FilePropertiesStorageFactory 一旦创建了jar,就可以使用常规的WildFly方法部署它:将jar复制到deploy/目录或使用jbosscli

在使用maven创建jar后,将jar复制到keydavet-6.0.1\standalone\deployments文件夹。但是我在用户联盟列表中没有看到我的提供商

如有任何建议/帮助,将不胜感激


提前感谢您的建议。

万一有人遇到这样的问题:

由于META-INF/services文件夹,用户存储SPI未显示。文档中有提供,但不清楚

在src/main/resources中,创建一个文件夹结构META-INF/services

创建一个名为org.keydape.storage.UserStorageProviderFactory的文件。整个过程就是META-INF/services目录中的文件名。其内容是SPI的完全限定类名: com.test.UserSpi


万一有人遇到这样的问题:

由于META-INF/services文件夹,用户存储SPI未显示。文档中有提供,但不清楚

在src/main/resources中,创建一个文件夹结构META-INF/services

创建一个名为org.keydape.storage.UserStorageProviderFactory的文件。整个过程就是META-INF/services目录中的文件名。其内容是SPI的完全限定类名: com.test.UserSpi


我不太确定你需要什么。让我们首先区分身份验证SPI联合身份检查和用户提供程序SPI联合用户。该文件的第一部分第8节-更多地关注于针对外部服务对用户进行身份验证-类似于facebook或谷歌。联邦用户存储更像是您在遗留系统中拥有自己的用户,这些用户具有遗留角色结构,您基本上希望通过keydape管理这些用户,或者通过导入这些用户,或者通过一些API查询这些用户,这将是该文档的第11节。所以,请决定什么才是你真正需要的

第二,你提到:

>  User is presented keycloak login screen. Onsubmission User is
> validated against external Datasource.
> 
> Retrieve some attributes from external datasource, map it to
> keycloak's id and access token.
> 
> Also put in a condition of user restriction of same user logging in
> multiple times at the same time.
> 
> I was thinking, it could be solved by retrieving user session
> information that's available in the keycloak datasource. If i use
> external datasource, does keycloak still maintain session information?
您的意思是:从外部数据源中检索一些属性,将其映射到KeyClope的id和访问令牌?通常,您只检索用户核心信息,还可能检索角色和其他自定义属性,而不是会话信息。KeyClope本身作为一个基于openIDConnect的授权服务器,将生成acces令牌,该令牌已经包含了关于谁可以访问哪些受保护资源的信息,因此您实际上不需要从其他地方导入任何会话,也不必担心所述令牌的生成

关于:也把同一用户登录的用户限制条件 同时多次。你到底想完成或避免什么?当您第一次登录时,您的客户收到有效期为X时间的持票人代币,在此期间您无需再次登录,直到代币过期或注销;同样,身份验证服务器负责的事情,而不是您实现的事情。你有更具体的要求吗

我在想,可以通过检索KeyClope数据源中可用的用户会话信息来解决这个问题。如果我使用外部数据源,KeyClope是否仍然维护会话信息?这听起来不对,你指的是什么会话数据?或者你需要访问?您的用户数据、作用域、角色等可以通过KeyClope Rest API访问。你
r外部数据源用于与用户相关的核心数据,而不是外部会话,为什么您认为需要导入外部会话?

我不确定您需要什么。让我们首先区分身份验证SPI联合身份检查和用户提供程序SPI联合用户。该文件的第一部分第8节-更多地关注于针对外部服务对用户进行身份验证-类似于facebook或谷歌。联邦用户存储更像是您在遗留系统中拥有自己的用户,这些用户具有遗留角色结构,您基本上希望通过keydape管理这些用户,或者通过导入这些用户,或者通过一些API查询这些用户,这将是该文档的第11节。所以,请决定什么才是你真正需要的

第二,你提到:

>  User is presented keycloak login screen. Onsubmission User is
> validated against external Datasource.
> 
> Retrieve some attributes from external datasource, map it to
> keycloak's id and access token.
> 
> Also put in a condition of user restriction of same user logging in
> multiple times at the same time.
> 
> I was thinking, it could be solved by retrieving user session
> information that's available in the keycloak datasource. If i use
> external datasource, does keycloak still maintain session information?
您的意思是:从外部数据源中检索一些属性,将其映射到KeyClope的id和访问令牌?通常,您只检索用户核心信息,还可能检索角色和其他自定义属性,而不是会话信息。KeyClope本身作为一个基于openIDConnect的授权服务器,将生成acces令牌,该令牌已经包含了关于谁可以访问哪些受保护资源的信息,因此您实际上不需要从其他地方导入任何会话,也不必担心所述令牌的生成

关于:也把同一用户登录的用户限制条件 同时多次。你到底想完成或避免什么?当您第一次登录时,您的客户收到有效期为X时间的持票人代币,在此期间您无需再次登录,直到代币过期或注销;同样,身份验证服务器负责的事情,而不是您实现的事情。你有更具体的要求吗

我在想,可以通过检索KeyClope数据源中可用的用户会话信息来解决这个问题。如果我使用外部数据源,KeyClope是否仍然维护会话信息?这听起来不对,你指的是什么会话数据?或者你需要访问?您的用户数据、作用域、角色等可以通过KeyClope Rest API访问。您的外部数据源用于与用户相关的核心数据,而不是外部会话,为什么您认为需要导入外部会话

好的,您澄清了您需要一个用户商店提供程序API。伟大的

现在,关于您的第二个问题/挑战:

从外部数据源检索一些属性,将其映射到KeyClope的id和访问令牌。需要检索用户的唯一id,并将其添加为jwt中的主题id。这就是id,当此令牌传递给其他服务时,其他服务可以使用它来检索id

为此,您所能做的最好是:

当用户属性在管理控制台上看到这些数据时,添加这些用户的唯一数据

使用用户属性的映射器在KeyClope上创建客户机作用域 将要从用户添加的属性映射到Id令牌和访问令牌。您还需要将您的客户机与刚刚创建的客户机范围联系起来。这听起来可能有点让人困惑,但这段视频是很棒的素材,我相信它会对你有很大帮助:在6:30左右,你会看到如何向你的代币添加额外的用户信息

也可以查看这个页面:当你粘贴编码的标记时,你可以看到它们的内容,这对开发者来说是一个很好的工具

当你提出你的解决方案时,我会帮助你完成这个独特的环节,或者你把它作为一个不同的问题发布,因为这是一个不同的问题

希望能有帮助

好的,您澄清了您需要一个用户商店提供程序API。伟大的

现在,关于您的第二个问题/挑战:

从外部数据源检索一些属性,将其映射到KeyClope的id和访问令牌。需要检索用户的唯一id,并将其添加为jwt中的主题id。这就是id,当此令牌传递给其他服务时,其他服务可以使用它来检索id

为此,您所能做的最好是:

当用户属性在管理控制台上看到这些数据时,添加这些用户的唯一数据

使用用户属性的映射器在KeyClope上创建客户机作用域 将要从用户添加的属性映射到Id令牌和访问令牌。您还需要将您的客户机与刚刚创建的客户机范围联系起来。这听起来可能有点让人困惑,但这段视频是很棒的素材,我相信它会对你有很大帮助:在6:30左右,你会看到如何向你的代币添加额外的用户信息

也可以查看这个页面:当你粘贴编码的标记时,你可以看到它们的内容,这对开发者来说是一个很好的工具

当你提出你的解决方案时,我会帮助你完成这个独特的环节,或者你把它作为一个不同的问题发布,因为这是一个不同的问题


希望能有所帮助。

谢谢@tony_008的评论。我将发布多条评论来回答你的问题。对此我深表歉意,这是因为字符限制。我从Authenticator的自定义验证器开始
正在对外部数据源进行初始化。正如你早些时候指出的那样,这不是为它准备的。现在,我开始实现用户提供者SPI。联邦用户存储是我所需要的。它现在可以工作了,但有一些小故障。从外部数据源中检索一些属性,将其映射到KeyClope的id和访问令牌。需要检索用户的唯一id,并将其添加为jwt中的主题id。这就是id,当此令牌传递给其他服务时,其他服务可以使用它来检索id。将其映射到KeyClope的id和访问令牌。我指的是keydove的openId connect id令牌,它也被置于同一用户登录的用户限制条件下。同时多次。我需要解决的是,我需要防止同一用户同时从多个系统登录。所以,我认为最好的方法是在sigin上使用存储的会话信息验证它们。如果有更好的验证和预防方法,请给出建议/评论。感谢@tony_008的评论。我将发布多条评论来回答你的问题。很抱歉,这是因为字符限制。我从自定义验证器开始,针对外部数据源进行身份验证。正如你早些时候指出的那样,这不是为它准备的。现在,我开始实现用户提供者SPI。联邦用户存储是我所需要的。它现在可以工作了,但有一些小故障。从外部数据源中检索一些属性,将其映射到KeyClope的id和访问令牌。需要检索用户的唯一id,并将其添加为jwt中的主题id。这就是id,当此令牌传递给其他服务时,其他服务可以使用它来检索id。将其映射到KeyClope的id和访问令牌。我指的是keydove的openId connect id令牌,它也被置于同一用户登录的用户限制条件下。同时多次。我需要解决的是,我需要防止同一用户同时从多个系统登录。所以,我认为最好的方法是在sigin上使用存储的会话信息验证它们。如果有更好的方法来验证和防止,请给出建议/评论。@tony-008对于唯一的用户会话,我已经发布了一个单独的问题。请告诉我您的想法/建议。您对KeyClope用户会话限制有何想法。我已经使用ADMINRESTAPI完成了。获取管理员令牌并使用此端点/auth/admin/realms/{realmId}/users/{userId}/sessions检索用户会话并验证它。我觉得应该有更好的办法way@amj。我还没有实现这一点,但如果必须实现的话,我的方法如下:如果您转到管理领域/会话部分,您将看到每个用户/客户端/用户打开的会话数量。应该可以通过编程方式查询它们。在ProviderStore的自定义验证方法中,我将添加一个检查条件,即相关用户需要有0个预先存在的会话,而不仅仅是在使用密码时,如果使用令牌,则不需要更多,因为如果用户会话已经存在,则要避免创建令牌。通过这样做,重新颁发令牌应该一个接一个发生。@tony-008对于唯一用户会话,我已经发布了一个单独的问题。请告诉我您的想法/建议。您对KeyClope用户会话限制有何想法。我已经使用ADMINRESTAPI完成了。获取管理员令牌并使用此端点/auth/admin/realms/{realmId}/users/{userId}/sessions检索用户会话并验证它。我觉得应该有更好的办法way@amj。我还没有实现这一点,但如果必须实现的话,我的方法如下:如果您转到管理领域/会话部分,您将看到每个用户/客户端/用户打开的会话数量。应该可以通过编程方式查询它们。在ProviderStore的自定义验证方法中,我将添加一个检查条件,即相关用户需要有0个预先存在的会话,而不仅仅是在使用密码时,如果使用令牌,则不需要更多,因为如果用户会话已经存在,则要避免创建令牌。通过这样做,令牌的重新发布应该是一个接一个的。您可以共享所有文件的整个目录结构吗。还尝试创建UserStorage SPI。您可以共享所有文件的整个目录结构吗。还尝试创建用户存储SPI。