Backgorund:我正在嘗試為我的舊應用程式添加 UserStorageSPI,以便我們可以使用現有的用戶憑據登錄。我已按照本教程進行操作,示例應用程式的完整源代碼可在此處獲得。
此應用程式存盤明文密碼并直接比較它們。但是,我的舊資料庫以加密格式存盤密碼。為了測驗示例用戶,我以 bcrypt 格式存盤了憑據,并在我的 CustomUserStorageProvider 類中覆寫了以下方法 (isValid(...))。
方法一:
public class CustomUserStorageProvider implements UserStorageProvider,
UserLookupProvider,
CredentialInputValidator,
UserQueryProvider {
....
@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput credentialInput) {
log.info("[I57] isValid(realm={},user={},credentialInput.type={})",realm.getName(), user.getUsername(), credentialInput.getType());
if( !this.supportsCredentialType(credentialInput.getType())) {
return false;
}
StorageId sid = new StorageId(user.getId());
String username = sid.getExternalId();
try ( Connection c = DbUtil.getConnection(this.model)) {
log.info("Username to query :: " username);
PreparedStatement st = c.prepareStatement("select password from users where username = ?");
st.setString(1, username);
st.execute();
ResultSet rs = st.getResultSet();
log.info("RS " rs);
if ( rs.next()) {
String pwd = rs.getString(1);
log.info("Password coming from query :: " pwd);
log.info("Password coming from user input :: " credentialInput.getChallengeResponse());
PasswordEncoder enc = new BCryptPasswordEncoder();
log.info(" enc.matches(pwd, credentialInput.getChallengeResponse()) " enc.matches(pwd, credentialInput.getChallengeResponse()));
return enc.matches(pwd, credentialInput.getChallengeResponse());
}
else {
return false;
}
}
catch(SQLException ex) {
throw new RuntimeException("Database error:" ex.getMessage(),ex);
}
}
}
當我將 jar 放在相關路徑中時,keycloak 可以讀取自定義提供程式。我還可以看到 keycloak 正在顯示來自這個新資料庫的所有匯入用戶,但是,我在 keycloak 日志中得到以下例外,而代碼正在嘗試比較密碼。
2022-06-24 15:53:30,566 INFO [com.test.spi.provider.CustomUserStorageProvider] (executor-thread-2) RS org.postgresql.jdbc.PgResultSet@75dadacb
2022-06-24 15:53:30,566 INFO [com.test.spi.provider.CustomUserStorageProvider] (executor-thread-2) Password coming from query :: $2a$12$rrtl/vDlCCF0cK0aKu5H6uW30B4fp9cIrTQlHPMayQTR9ToZicEoW
2022-06-24 15:53:30,566 INFO [com.test.spi.provider.CustomUserStorageProvider] (executor-thread-2) Password coming from user input :: test
2022-06-24 15:53:30,567 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-2) Uncaught server error: java.lang.NoClassDefFoundError: org/springframework/security/crypto/password/PasswordEncoder
at com.test.spi.provider.CustomUserStorageProvider.isValid(CustomUserStorageProvider.java:147)
at org.keycloak.credential.UserCredentialStoreManager.lambda$validate$4(UserCredentialStoreManager.java:164)
at java.base/java.util.Collection.removeIf(Collection.java:576)
at org.keycloak.credential.UserCredentialStoreManager.validate(UserCredentialStoreManager.java:164)
at org.keycloak.credential.UserCredentialStoreManager.isValid(UserCredentialStoreManager.java:151)
at org.keycloak.credential.UserCredentialStoreManager.isValid(UserCredentialStoreManager.java:110)
at org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.validatePassword(AbstractUsernameFormAuthenticator.java:229)
at org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.validateUserAndPassword(AbstractUsernameFormAuthenticator.java:150)
at org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.validateForm(UsernamePasswordForm.java:55)
at org.keycloak.authentication.authenticators.browser.UsernamePasswordForm.action(UsernamePasswordForm.java:48)
at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:169)
at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:990)
at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:321)
at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:292)
at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:276)
at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:349)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:82)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:42)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:67)
at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:55)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:380)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:358)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$1(QuarkusRequestFilter.java:71)
at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:159)
at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:100)
at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$1(ContextImpl.java:157)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:543)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.ClassNotFoundException: org.springframework.security.crypto.password.PasswordEncoder
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at io.quarkus.bootstrap.runner.RunnerClassLoader.loadClass(RunnerClassLoader.java:107)
at io.quarkus.bootstrap.runner.RunnerClassLoader.loadClass(RunnerClassLoader.java:57)
... 65 more
我還嘗試在啟動應用程式中將 PasswordEncoder 添加為 Bean,并將其添加為 CustomUserStorageProvider 類中的 Autowired 依賴項,但我得到了同樣的例外。
方法2:
@SpringBootApplication
public class SpiApplication {
public static void main(String[] args) {
SpringApplication.run(SpiApplication.class, args);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
-----
@Service
public class CustomUserStorageProvider implements UserStorageProvider,
UserLookupProvider,
CredentialInputValidator,
UserQueryProvider {
@Autowired
PasswordEncoder enc ;
我的 pom.xml 依賴項在這里:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>18.0.0</version>
</dependency>
<!-- User Storage SPI dependency -->
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
<version>18.0.0</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
<version>18.0.0</version>
</dependency>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
我正在使用此命令生成 jar 檔案并將其保存在 keycloak-18.0.0/providers/ 包中。
mvn package
請用正確的方法幫助我。我也在這個論壇上瀏覽了幾篇博客文章和問題,但沒有得到正確的解決方案。TIA。
主要問題:我什至在 Eclipse 中設定了這個專案,并嘗試將專案匯出為 jar 檔案(可運行的 jar/jar 兩者)。生成的far jar 很大。陰影插件創建的 32 MB 而不是 16 KB,但例外情況保持不變。為什么這個依賴沒有被添加到 jar 的類路徑中?我不能讓使用這個 jar 的 3rd 方應用程式添加類路徑,所以它必須嵌入到最終的 jar 中。請幫忙。我已經花了很多時間,并且正在嘗試新的解決方法。
uj5u.com熱心網友回復:
謝天謝地,我找到了這篇文章,它對我有用。
https://github.com/keycloak/keycloak/issues/10230
總結一下,
添加
org.keycloak keycloak-server-spi ${keycloak.version} 提供 org.postgresql postgresql 42.3.6 提供providedkeycloak、login、Postgres 或 keycloak 可能已經具有的任何依賴項的范圍。這就是我更新后的 Maven 的樣子,<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.36</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-crypto</artifactId> <version>5.7.1</version> </dependency>利用 Maven 程式集插件并使用以下命令執行它。另一個答案的有用帖子。命令 :
mvn clean compile assembly:single
插入 :
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>my-user-provider</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</plugin>
</plugins>
</build>
以上2次修改,修復了我的東西。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/498140.html
標籤:爪哇 行家 可执行jar maven-程序集插件 胖子
