Keycloak:无法在 Spring Boot 应用程序中加载 URL

Posted

技术标签:

【中文标题】Keycloak:无法在 Spring Boot 应用程序中加载 URL【英文标题】:Keycloak: Failed to load URLs in Spring Boot Application 【发布时间】:2020-07-23 08:08:44 【问题描述】:

我目前正在尝试开发一个使用 keycloak 保护的 Spring Boot Rest Api。

当我尝试调用必须识别用户的 api 时出现错误。

错误信息如下:

2020-04-10 16:09:00.324  WARN 44525 --- [nio-8080-exec-7] 
o.keycloak.adapters.KeycloakDeployment   : Failed to load URLs from 
https://keycloakserver.de/auth/realms/realm/.well-known/openid-configuration

java.lang.RuntimeException: java.lang.RuntimeException: Stub!
at org.keycloak.adapters.KeycloakDeployment.getClient(KeycloakDeployment.java:327) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.KeycloakDeployment.getOidcConfiguration(KeycloakDeployment.java:219) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.KeycloakDeployment.resolveUrls(KeycloakDeployment.java:178) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.KeycloakDeployment.getRealmInfoUrl(KeycloakDeployment.java:232) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.rotation.AdapterTokenVerifier.createVerifier(AdapterTokenVerifier.java:107) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.rotation.AdapterTokenVerifier.verifyToken(AdapterTokenVerifier.java:47) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.BearerTokenRequestAuthenticator.authenticateToken(BearerTokenRequestAuthenticator.java:103) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.BearerTokenRequestAuthenticator.authenticate(BearerTokenRequestAuthenticator.java:88) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.RequestAuthenticator.authenticate(RequestAuthenticator.java:67) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.attemptAuthentication(KeycloakAuthenticationProcessingFilter.java:154) [keycloak-spring-security-adapter-9.0.2.jar:9.0.2]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96) [keycloak-spring-security-adapter-9.0.2.jar:9.0.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:97) [spring-web-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]

我不知道Failed to load URLs from 是什么意思。当我单击链接并显示配置文件时,我可以访问此端。

设置

钥匙斗篷:

Keycloak 服务器在网络中,所以没有 localhost。

我创建了一个领域(测试领域) 我创建了一个客户端(测试客户端) 我创建了一个用户(测试用户) 我在创建的客户端 (ADMIN) 中有一个角色 我已将角色 (ADMIN) 分配给用户 (test-user)

客户端的客户端协议为openid-connect,访问类型为confidental

春季启动:

Spring Boot REST 应用程序正在 localhost:8080 上运行。

我在 keycloak 配置之后添加了 applications.properties

keycloak.realm=test-realm
keycloak.auth-server-url = https://keycloakserver.de/auth
keycloak.resource = test-client
keycloak.ssl-required=external
keycloak.bearer-only=true
keycloak.principal-attribute=preferred_username
keycloak.use-resource-role-mappings = true

为了确保测试用户只能访问一个 api 调用,我使用以下配置。

 @Override
    protected void configure(HttpSecurity http) throws Exception 
        super.configure(http);
        http.authorizeRequests()
                .antMatchers("/getTest")
                .hasRole("ADMIN")
                .anyRequest()
                .authenticated();
    

测试

当我用 Postman 拨打 http://localhost:8080/getTest 时,我得到了正确的 401 Unauthorized

然后我用Authorization 和登录的test-user 的访问令牌调用了相同的URL。

通过第二次调用,我收到了上面的错误消息。

有人知道吗? 如果我错过了您需要知道的配置值,请询问。

感谢您的帮助。

编辑:

SecurityConfig.java

import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootProperties;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

/**
 * Created by johannes on 07.04.20 for test App.
 */
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
@Configuration
@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter 

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        auth.authenticationProvider(keycloakAuthenticationProvider);
    

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() 
        return new RegisterSessionAuthenticationStrategy(
                new SessionRegistryImpl());
    

    @Bean
    @Primary
    public KeycloakConfigResolver keycloakConfigResolver(KeycloakSpringBootProperties properties) 
        return new CustomKeycloakSpringBootConfigResolver(properties);
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        super.configure(http);
        http.authorizeRequests()
                .antMatchers("/getTest")
                .hasRole("ADMIN")
                .anyRequest()
                .authenticated();
    

CustomKeycloakSpringBootConfigResolver:

import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootProperties;
import org.springframework.context.annotation.Configuration;

/**
 * Created by johannes on 10.04.20 for test App.*/
@Configuration
public class CustomKeycloakSpringBootConfigResolver extends KeycloakSpringBootConfigResolver 
        private final KeycloakDeployment keycloakDeployment;
    public CustomKeycloakSpringBootConfigResolver(KeycloakSpringBootProperties properties) 

        keycloakDeployment = KeycloakDeploymentBuilder.build(properties);
    

    @Override
    public KeycloakDeployment resolve(HttpFacade.Request facade) 
        return keycloakDeployment;
    

TestController.java(这只是测试 getter):

  @GetMapping("/getTest")
    public @ResponseBody ResponseEntity getTest() 

        return ResponseEntity.status(ResponseValues.ITEMDELETEFAILED.getResponseCode()).body(ResponseValues.ITEMDELETEFAILED.getResponseMessage());

    

请求是通过邮递员提出的,代码如下:

curl --location --request GET 'http://localhost:8080/getTest' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUI...' \
--header 'Cookie: JSESSIONID=41E8E82178FA181817...'

【问题讨论】:

【参考方案1】:

就我而言:领域名称不正确。它区分大小写。当我将其更改为:

keycloak.realm = demo

我写过

keycloak.realm = Demo

【讨论】:

【参考方案2】:

我遇到了同样的问题,对我来说它也与有缺陷的配置值有关。

keycloak.auth-server-url = https://keycloakserver.de/auth

首先我忘记了/auth,然后我使用了http 而不是https

【讨论】:

添加 /auth 成功了,谢谢 :)【参考方案3】:

尝试将hasRole更改为hasAuthority或在hasRole("ROLE_ADMIN")这样的角色前添加前缀ROLE_

【讨论】:

还是一样。我得到一个响应代码 500,我的 spring 后端抛出“无法从 https://keycloakserver.de/auth/realms/realm/.well-known/openid-configuration 加载 URL”错误跨度> 你能分享控制器代码以及你是如何提出请求的 我用代码更新了我的初始问题。感谢您的帮助。【参考方案4】:

我自己解决了这个问题。

我注意到我的 spring boot sdk 是一个 android sdk。我不知道这怎么会发生。 我将它更改为 java sdk,它就像一个魅力。

【讨论】:

【参考方案5】:

我遇到了类似的问题。就我而言,我没有意识到我的 application.properties 文件中的“keycloak.auth-server-url”末尾有一个空格。

这样,keycloak 适配器尝试访问无效的 URL。

也许这可以帮助遇到类似问题并找到此线程的人。

【讨论】:

【参考方案6】:

我为 keycloak.auth-server-url 输入了错误的值。

【讨论】:

这已经在其他答案中提到了。 在回答已有答案的旧问题时,请确保提供新颖的解决方案或比现有答案更好的解释。

以上是关于Keycloak:无法在 Spring Boot 应用程序中加载 URL的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 中的 Keycloak 无法应用 Liquibase 补丁

使用 KeycloakAutoConfiguration 无法使用 Spring Boot Security UnsatisfiedDependencyException 设置 Keycloak

示例 keycloak spring-boot 应用程序无法找到 bean KeycloakSpringBootConfigResolver

Spring Boot - 无法通过 Zuul 代理获得 Keycloak 授权 api 的响应

Keycloak Spring Boot 适配器和匿名资源

如何在 Spring Boot 应用程序中使用 Keycloak Policy Enforcer