我正在尝试实现自定义密钥克隆Authenticator SPI,以针对外部数据源进行身份验证。 Spring boot Rest Service也可用,我也可以使用它。
我要解决的用例是
向用户显示密钥斗篷登录屏幕。提交用户已针对外部数据源进行了验证。
从外部数据源检索一些属性,将其映射到keycloak的ID和访问令牌。
还设置了相同用户同时登录多次的用户限制条件。
我当时在想,可以通过检索keycloak数据源中可用的用户会话信息来解决。如果我使用外部数据源,keycloak仍会保留会话信息吗?
我遵循了官方指南(https://www.keycloak.org/docs/latest/server_development/index.html#_auth_spi_walkthrough)第8.3节,该节与我所需要的非常相似。
现在我按照第11(https://www.keycloak.org/docs/latest/server_development/index.html#_user-storage-spi)节的规定开始学习,似乎也很合适。
我所做的是从实现自定义身份验证器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;
}
};
}
遵循文档(https://www.keycloak.org/docs/latest/server_development/index.html#packaging-and-deployment-2)
我们的提供程序实现的类文件应放在jar中。您还必须在META-INF / services / org.keycloak.storage.UserStorageProviderFactory文件中声明提供程序工厂类。
这里的问题是:我创建的jar在“ META-INF”文件夹中没有services目录,我需要手动创建并添加它吗?
org.keycloak.examples.federation.properties.FilePropertiesStorageFactory 一旦创建了jar,就可以使用常规的WildFly方式进行部署:将jar复制到deploy /目录或使用JBoss CLI。
使用maven创建jar之后,将jar复制到“ keycloak-6.0.1 \ standalone \ deployments”文件夹中。但我在“用户联合身份列表”中看不到我的提供者
任何建议/帮助将不胜感激!
预先感谢您的建议。
答案 0 :(得分:2)
好吧,您澄清了,您需要一个User Store Provider API。很棒
现在您的第二个“问题/挑战”:
从外部数据源检索一些属性,将其映射到keycloak的ID和访问令牌。需要检索用户的唯一ID并将其作为主题ID添加到jwt中。这就是ID,当此令牌传递给其他服务时,其他服务便可以用来检索ID。
为此,您可以做的最好的事情是:
将这些用户的唯一数据添加为用户属性(请在管理控制台上查看)
在Keycloak上创建一个“客户端作用域”,并为“用户属性”创建一个映射器 将您想要(从用户)添加到ID令牌和访问令牌的属性映射。您还需要将客户与刚刚创建的“客户范围”联系在一起。这听起来可能有点令人困惑,但是该视频非常棒,我相信可以帮助您:https://www.youtube.com/watch?v=ZxpY_zZ52kU(大约6:30左右,您将看到如何向令牌添加额外的用户信息)< / p>
也请检出此页面:https://jwt.io/(当您在其中粘贴编码的令牌时,您可以看到它们的内容),对于开发人员来说是个不错的工具。
在您提出解决方案时,我将为您提供独特的会话,或者将其发布为其他问题,因为这是一个不同的问题。
希望有帮助。
答案 1 :(得分:1)
万一有人遇到这样的问题:
由于META-INF / services文件夹,未显示UserStorage SPI。它在文档中提供,但不清楚
在src / main / resources中,创建文件夹结构META-INF / services
在META-INF / services目录中创建一个名为org.keycloak.storage.UserStorageProviderFactory的文件(整个东西是文件名)。它的内容是您的SPI的完全限定的类名: com.test.UserSpi
答案 2 :(得分:0)
我不确定您需要什么。让我们先区分身份验证SPI(联合身份检查)与用户提供者SPI(联合用户)。第一个(文档的第8节-更多地专注于针对外部服务(类似于Facebook或google)对用户进行身份验证)。联合用户存储更像是将您的awn用户放置在具有旧版“角色结构”的旧版系统中,并且您基本上是想通过viecloak(通过导入它们或通过某些API查询via)来管理它们。该文档的11)。因此,请确定您确实需要什么。
2,您提到以下内容:
> 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?
您是什么意思: 从外部数据源中检索一些属性,将其映射到keycloak的ID和访问令牌。 ?通常,您只检索用户核心信息,还可能检索角色和其他自定义属性(而不是会话信息)。 Keycloak本身作为基于openIDConnect的授权服务器,将生成acces令牌,该令牌已包含有关谁可以访问哪些受保护资源的信息,因此您实际上不需要从其他任何地方导入任何会话,也不必担心所述令牌的生成
关于: 还设置了相同用户登录的用户限制条件 。 。当您第一次登录时,您的客户到底想达到什么目的(或避免?),在这段时间内,您的客户收到了有效期为X的有效期的Bearer令牌。无需再次登录自己,直到令牌过期或被窃取为止;再次由您的Auth服务器处理,而不是由您实施。您想要更具体的内容吗?
我当时在想,可以通过检索keycloak数据源中可用的用户会话信息来解决。如果我使用外部数据源,keycloak仍会保留会话信息吗? 听起来不对,您指的是什么会话数据?还是您需要访问?您的用户数据,范围,角色等可以通过KEycloak Rest API(https://www.keycloak.org/docs-api/6.0/rest-api/index.html#_overview)访问。您的外部数据源用于与用户相关的核心数据(而不是外部会话),为什么您认为需要导入外部会话?