我正在努力从旧的数据库存储中迁移出来。我们创建了一个用户存储 SPI,允许我们使用旧系统来验证凭据。目前这有效。我们在自定义 CredentialInputValidator.isValid 函数中验证凭据。我们想要做的是,旧系统的登录是有效的,我们想要创建一个与用户匹配的本地用户帐户并附加凭据。
据我了解,这应该工作的方式是:
Login ->
-> Hits Custom User Storage SPI
-> On Success
-> Create local user account if not exists
-> Attach new password credentials
-> Is Logged In
Log Out
Log In ->
-> Checks Keycloak Local Users
-> User Storage SPI is never checked, because the local account was previously created.
-> UN/PW check
-> (failure happens here)
-> Is Logged In
这就是它应该如何工作。不幸的是,无论我尝试什么,它都不会让我第二次登录(也不会尝试再次访问用户存储 SPI,因为本地帐户存在)。我可以看到用户和凭据是在用户下的领域中创建的;我可以在 public.user_entity 和 public.credential 表中看到用户和凭证行。
无论我如何尝试,我都无法登录本地帐户。
下面是我的 isValid 函数。谁能帮我找出我做错了什么?
@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
UserCredentialModel cred = (UserCredentialModel)input;
String password = cred.getValue();
// Login to the legacy system.
String loginOutput = loginCMD(user.getUsername(), password, xForwardedFor);
// Falures return a simple string "false"
Boolean valid = !loginOutput.equals("false");
if (!valid) {
return valid;
}
// Store the user back to Keycloak.
UserModel local = UserStoragePrivateUtil.userLocalStorage(session).getUserByUsername(realm, user.getUsername());
if (local != null) {
return valid;
}
local = UserStoragePrivateUtil.userLocalStorage(session).addUser(realm, user.getUsername());
local.setFirstName("firstName");
local.setLastName("lastName");
local.setEmail(user.getUsername());
local.setEnabled(true);
local.setUsername(user.getUsername());
Pbkdf2PasswordHashProvider encoder = new Pbkdf2PasswordHashProvider(
Pbkdf2Sha512PasswordHashProviderFactory.ID,
Pbkdf2Sha512PasswordHashProviderFactory.PBKDF2_ALGORITHM,
Pbkdf2Sha512PasswordHashProviderFactory.DEFAULT_ITERATIONS,
256 // Tried setting this to 512, as well, no dice.
);
PasswordCredentialModel pcm = encoder.encodedCredential(password, Pbkdf2Sha512PasswordHashProviderFactory.DEFAULT_ITERATIONS);
Date date = new Date();
pcm.setCreatedDate(date.getTime());
pcm.setUserLabel("user-spi migration");
if (!local.credentialManager().isConfiguredFor(input.getType())) {
try {
local.credentialManager().createStoredCredential(pcm);
} catch (Exception e) {
e.printStackTrace();
}
}
return valid;
}
我尝试使用凭据创建本地用户,并使用该帐户登录。帐户和凭据已创建,但登录始终失败并显示
DEBUG [org.keycloak.credential.PasswordCredentialProvider](executor-thread-1)用户[已编辑]密码验证失败
您需要实现两个接口UserLookupProvider、CredentialInputValidator。
提到 LookupProvider 是在方法 getUserByUsername 上预先调用的,这必须返回一个有效的用户对象。仅当成功时,才会调用 isValid 方法。