我已经实现了keycloak用户存储SPI流。它针对外部源进行身份验证。Keycloak是用外部存储属性更新的,如果它在getUserByUsername方法中更新,它就可以工作。
我正在isValid方法中验证userValidation,并更新UserModel和LocalHashMap中的userAttributes。
从日志中,我看到UserStoreProviderFactory创建了两个实例来验证一个事务/登录
为什么在第一次userStorageProvider调用时多次调用getUserByUserName()方法
UserStorageProviderFactory
-> Creates instance of UserStorageProvider
-> UserStorage provider calls getUserById method
-> UserStorage provider calls getUserByUserName method
-> UserStorage provider calls isValid method
on true, keycloak
UserStorageProviderFactory
-> Creates instance of UserStorageProvider
-> UserStorage provider calls getUserById method
-> UserStorage provider calls getUserByUserName method
returns UserModel
@Override
public UserModel getUserById(String id, RealmModel realm) {
logger.debug("__ ########## getUserById ID:" + "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
*/
@Override
public UserModel getUserByUsername(String username, RealmModel realm) {
logger.debug("__ %%%%%%%%%% getUserByUsername ID:" + username + ":REALM:" + realm);
logger.debug("Provider Num:" + this.randomNum);
UserModel userModel = loadedUsers.get(username);
UserModel local = session.userLocalStorage().getUserByUsername(username, realm);
logger.debug("*#@#$ local session:" + local);
if (userModel == null) {
logger.debug("In NULLLLLLLLLLLLLLLLLLL ");
userModel = createUserModel(realm, username);
// set for demo...
userModel.setSingleAttribute("externalId", Integer.toString(10));
} else {
logger.debug("__ ELSEEEEEEEEEEEEEE getUserByUsername sku:" + userModel.getFirstAttribute("sku"));
userModel.setSingleAttribute("externalId", Integer.toString(12));
}
return userModel;
}
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
logger.debug("__ , 1111111111 isValid:input type:" + input.getType() + ":userName:" + user.getUsername());
UserCredentialModel cred = (UserCredentialModel)input;
if (!supportsCredentialType(input.getType())
|| !(input instanceof UserCredentialModel)) {
logger.warn("__, credentialType: " + input.getType() + ": NOT supported");
return false;
}
UserDTO model = new UserDTO();
model.setEmailId(user.getUsername());
model.setPassword(cred.getValue());
try {
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target(properties.getProperty("userUrl"));
Response response = target.request().post(
Entity.entity(model, "application/json"));
ResponseDTO<UserResponseDTO> responseDto = response.readEntity(new GenericType<ResponseDTO<UserResponseDTO>>() {});
logger.debug("__ , !!!!!!!!!!! json response:" + responseDto);
logger.debug("!!!! Provider Num:" + this.randomNum);
if (responseDto.getCode() == 200) {
UserResponseDTO userResponseDto = responseDto.getData();
UserDetailsDTO userDetailsDto = userResponseDto.getDetails();
user.setEmail(userDetailsDto.getEmailId());
user.setFirstName(userDetailsDto.getFirstName());
logger.debug("!!!!@@@@@@@@ Provider Num:" + this.randomNum);
logger.debug("__ , returning success from isValid:" + user.getUsername() +":::");
loadedUsers.put(user.getUsername(), user);
return true;
}
response.close();
} catch(Exception ex) {
logger.error("Exception Occured accessing:", ex);
}
return false;
}
日志(为了显示调用getUserById()和getUserByUserName()方法的次数,UserStorageFactory实例化了两次UserStorageProvider实例)
2019-08-30 08:49:26,273调试[org.test.keycloak.userstore.factory.TestUserStoreProviderFactory](默认任务-2)用户URL:http://localhost:8280/login
2019-08-30 08:49:26,960 DEBUG[org.test.keycloak.userstore.testUserStoreProvider](默认任务-2)__%%%%%%%%%%%getUserByUsername ID:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmAdapter@64DDDA7a 2019-08-30 08:49:26,962 DEBUG[org.test.keycloak.userstore.testUserStoreProvider](默认任务-2)LOADEDUSERS,TestUserStoreProvider](默认任务-2)在NulllLlLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL2019-08-30 08:49:26,965 DEBUG[org.test.keycloak.userstore.testUserStoreProvider](默认任务-2)__中,从isvalid:test@gmail.com:::
2019-08-30 08:49:26,966 DEBUG[org.test.keycloak.userstore.testUserStoreProvider](默认任务-2)__################getUserById ID:ID:F:4A65AC95-6B5D-4508-B7EC-348AE1DA619D:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmadapter@64DDDA7A 2019-08-30 08:49:26,986 DEBUG%%%%getUserByUsername ID:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmAdapter@64DDDA7a 2019-08-30 08:49:27,022 DEBUG[org.test.keycloak.userstore.testUserstoreProvider](默认任务
2019-08-30 08:49:27,056 DEBUG[org.test.keycloak.userstore.testUserStoreProvider](默认任务-2)__###############getUserById ID:ID:F:4A65AC95-6B5D-4508-B7EC-348AE1DA619D:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmadapter@64DDDA7A 2019-08-30 08:49:27,059 DEBUG%%%%getUserByUsername ID:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmadapter@64DDDA7A 2019-08-30 08:49:27,059 DEBUG[org.test.keycloak.userstore.testUserStoreProvider](默认任务-2)LOADEDUSERS,keysize:1 201 9-08-30 08:49:27,059 DEBUG[org.test.keycloak.userstore.testUserStoreProvider](默认任务-2)test.keycloak.userstore.testUserStoreProvider](默认任务-2)__%%%%%%%%%%%getUserByUsername id:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmAdapter@64DDDA7a
2019-08-30 08:49:27,071 DEBUG[org.test.keycloak.userstore.testUserStoreProvider](默认任务-2)__###############getUserById ID:ID:F:4A65AC95-6B5D-4508-B7EC-348AE1DA619D:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmadapter@64DDDA7A 2019-08-30 08:49:27,073 DEBUG%%%%getUserByUsername ID:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmAdapter@64DDDA7A 2019-08-30 08:49:27,073 DEBUG[org.test.keycloak.userstore.testUserstoreProvider](默认任务-2)__ELSEEEEEEEEEEEEEE getUserByUsername sku:1
2019-08-30 08:49:29,421调试[org.test.keycloak.userstore.factory.testuserstoreProviderFactory](默认任务-2)用户URL:http://localhost:8280/login 2019-08-30 08:49:29,422调试[org.test.keycloak.userstore.testuserstoreProvider](默认任务-2).infinispan.realmadapter@64DDDA7A 2019-08-30 08:49:29,432 DEBUG[org.test.keycloak.userstore.testuserstoreProvider](默认任务-2)__%%%%%%%%%%getUserByUsername id:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmadapter@64DDDA7A 2019-08-30 08:49:29,432 DEBUG[org.test.keycloak.userstore.testuserstoreProvider](默认任务:29,581 DEBUG[org.test.keycloak.userstore.testUserStoreProvider](默认任务-2)__############getUserById ID:ID:F:4A65AC95-6B5D-4508-B7EC-348AE1DA619D:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmAdapter@64DDDA7A 2019-08-3008:49:29,581 DEBUG[org.test.keycloak.userstore.testUserStoreProvider](默认任务-2)__%%%%%%%%%%getUserByUsername id:test@gmail.com:realm:org.keycloak.models.cache.infinispan.realmAdapter@64DDDA7a
任何建议/提示,你可以帮助我解决/理解工作流程将非常感谢!
>
首先,创建一个UserProvider实例来通过登录流。在此流上更新的UserModel在外部不可用,除非它被缓存/存储
其次,使用下面的endpoint创建一个UserProvider实例来创建令牌。UserModel对象从getUserByUserName方法()返回。“http://localhost:8180/auth/realms/myapp/protocol/openid-connect/token”
若要存储具有自定义属性的UserModel,
this.session.userLocalStorage().addUser(realm, user.getUsername());
@Override
public UserModel addUser(RealmModel realm, String username) {
// userModel returned should be subclassed or instance of AbstractUserAdapterFederatedStorage
return this.myUserModel;
}
//ComponentModel ID of the provider. This sets a link between the provider and the imported user
user.setFederationLink(this.model.getId());
我正在尝试实现一个自定义密钥克拉克身份验证器SPI,用于针对外部数据源/REST服务进行身份验证。计划是将它们迁移到Keycloak。 成功后,在keycloak数据源上创建用户。 创建自定义映射器以在令牌上添加额外的用户属性。 我正在遵循官方指南https://www.keycloak.org/docs/latest/server_development/index.html#_auth_spi
我遵循了为keycloak(版本4.8.3)设置自定义身份验证器spi的演练。我几乎只使用从这里得到的示例代码。我只更改了以便能够编译项目并使用部署它。而且它起作用了...我可以在keycloak中配置新的身份验证流,更新浏览器流并设置所需的动作。但是,如果我想在应用程序中使用新的身份验证,我会得到以下消息:。并且在控制台中得到以下输出: 我在github上查找了文件DefaulTauthenti
我试图解决的用例是 用户将显示keycloak登录屏幕。Onsubmission用户将根据外部数据源验证。 从外部数据源中检索一些属性,将其映射到KeyCloak的id和访问令牌。 我所做的是从实现自定义身份验证器SPI开始,认为这不是正确的方法,现在实现了UserStorageProvider。 遵循文档(https://www.keycloak.org/docs/latest/server_d
我尝试将安装程序部署到本地存储库: --设置。xml-- --波姆。xml--- 当我执行“mvn部署”时,我收到错误: 艺术家日志: 如果我将服务器/存储库id更改为“myserver.com”-部署工作!但这不适合我,因为在myserver上,这不适用于svn。通用域名格式 我试图将标签“配置文件”和“镜像”添加到server.xml和“分发管理”添加到pom.xml-得到相同的错误 服务器/
在过去的几周里,我一直在努力掌握KeyClope,这样我就可以实现一种使用遗留提供商(基于Oracle,带有会话表和各种奇怪的东西)对用户进行身份验证的方法。我们计划在不久的将来解决这个问题,但目前我们必须解决这个问题,所以我们的想法是在前线使用KeyClope——利用它提供的主要好处,比如SSO——在需要身份验证的应用程序中省略传统的身份验证提供程序。 我读了一些关于构建自定义OIDC身份提供程
于是我在这里看到:https://firebase . Google . com/docs/auth/web/account-linking # link-auth-provider-credentials-to-a-user-account现在可以在Firebase中链接用户账号了。我还看到Firebase提供了匿名认证的功能,它为一个用户创建一个用户会话,不需要任何凭证。 在我们的应用程序中,