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

Posted

技术标签:

【中文标题】使用 KeycloakAutoConfiguration 无法使用 Spring Boot Security UnsatisfiedDependencyException 设置 Keycloak【英文标题】:Fail to setup Keycloak with Spring Boot Security UnsatisfiedDependencyException with KeycloakAutoConfiguration 【发布时间】:2019-04-04 20:23:49 【问题描述】:

keycloack 和 spring 安全性有点问题。

这里是 pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>my.world</groupId>
    <artifactId>having-fun</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>having-fun</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <keycloak.version>4.5.0.Final</keycloak.version>
        <kotlin.version>1.2.70</kotlin.version>
        <swagger.version>2.9.2</swagger.version>
    </properties>

    <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-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-kotlin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
        </dependency>


        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>$swagger.version</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>$swagger.version</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.keycloak.bom</groupId>
                <artifactId>keycloak-adapter-bom</artifactId>
                <version>$keycloak.version</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <sourceDirectory>$project.basedir/src/main/kotlin</sourceDirectory>
        <testSourceDirectory>$project.basedir/src/test/kotlin</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <profiles>
                        <profile>development</profile>
                        <profile>docker</profile>
                    </profiles>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>kotlin-maven-plugin</artifactId>
                <groupId>org.jetbrains.kotlin</groupId>
                <configuration>
                    <args>
                        <arg>-Xjsr305=strict</arg>
                    </args>
                    <compilerPlugins>
                        <plugin>spring</plugin>
                        <plugin>jpa</plugin>
                    </compilerPlugins>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>$kotlin.version</version>
                    </dependency>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-noarg</artifactId>
                        <version>$kotlin.version</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>


</project>

这是错误

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.0.RELEASE:run (default-cli) on project activation-service-backend: An exception occurred while running. null: InvocationTargetException: Unable to start web server; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tomcatServletWebServerFactory' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration$EmbeddedTomcat.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.keycloak.adapters.springboot.KeycloakAutoConfiguration': Unsatisfied dependency expressed through method 'setKeycloakConfigResolvers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through field 'keycloakConfigResolver'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'KeycloakConfigResolver': Requested bean is currently in creation: Is there an unresolvable circular reference? -> [Help 1]

知道什么是错的......我相信它来自 pom.xml 但我不知道为什么? 提前谢谢


多亏了这个 ***** 规则,我必须提供更多细节,即使现有的细节不多。所以我创建了一些没有任何内容的文本。如果你读到这里,请停下来,因为只有字母,没有信息……现在让我们试试,如果我写够了

【问题讨论】:

Keycloak 4.5.0 不是针对 2.1.0 启动 (github.com/keycloak/keycloak/blob/4.5.0.Final/adapters/oidc/…) 构建的,因此如果您可以检查旧版本的启动可能有助于缩小问题范围。您也可以尝试 jetty 或 undertow 来查看该错误是否特定于默认嵌入式 tomcat 我有 spring boot 2.1.0.RELEASE 和 Keycloak 4.5 集成工作,但我没有使用任何 keycloak jars。请参阅此处的文档 keycloak.org/docs/latest/securing_apps/… 和 keycloak.org/docs/latest/securing_apps/… 另外,如果你正在构建资源服务器,我建议使用 Spring 5.1 安全特性来设置资源服务器。 我已经阅读了@ChirdeepTomar 的文档,但我看不出做错了什么......甚至添加他们提到的这个过滤器注册bean .. 是否可以只使用简单的 OAuth 和 Keycloak 和 Spring Boot Security? @RyanDawson 我也尝试过使用 spring boot 2.0.3 但它也不起作用...... 【参考方案1】:

确保您在 build.gradle 或 pom.xml 中有以下依赖项

"org.springframework.boot:spring-boot-starter-web",
            "org.springframework.boot:spring-boot-starter-security",
            "org.springframework.security:spring-security-oauth2-jose",
            "org.springframework.security.oauth:spring-security-oauth2:2.3.4.RELEASE",
            "org.springframework.security:spring-security-oauth2-resource-server"

应用程序.yaml

spring:
  application:
    name: sociter
  security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: http://localhost:8080/auth/realms/REALM_NAME/protocol/openid-connect/certs
          issuer-uri: http://localhost:8080/auth/realms/REALM_NAME

并在此处设置网络安全:

https://github.com/jzheaux/messaging-app/blob/master/resource-server/src/main/java/sample/config/ResourceServerConfig.java

更多详情:https://spring.io/blog/2018/08/21/spring-security-5-1-0-rc1-released#oauth2-resource-server

【讨论】:

谢谢 .. 但是如果我还想提供从 REST API 登录的可能性,那么我必须像客户端一样行事吗?不仅仅是资源服务器? 阅读 Keycloak 客户端上的 Access_Type。 REST API 是受 Bearer Token 保护的后端服务,因此您无法登录 API,您需要在 Authorization 标头中传入 Bearer Token 才能访问 API。文档:keycloak.org/docs/latest/server_admin/index.html#oidc-clients 很抱歉问的有点愚蠢......我想要的是一个带有 REST API 的微服务,它由 Spring Security 使用 OAuth2 和例如用于身份验证的密钥斗篷。如果没有提供有效的 JWT,微服务应该重定向到 keycloak,并希望返回一个有效的 JWT。这有什么不对吗?目前我有点迷茫:-) 别担心 :) 执行重定向不是微服务的责任,微服务只是一个后端 API,它只需要来自某些 OIDC 提供商(如 Keycloak、Okta、Auth0 或 AzureAD)的有效令牌。您将 JWT 传递到 Spring Boot 微服务中,无论是 SPA、移动应用程序还是桌面应用程序,您的前端都将使用 Keycloak 进行身份验证以获取该 JWT 令牌。无论是重定向还是从 SPA 到令牌端点的调用,都取决于您正在构建的客户端类型。 邮递员:你应该叫这个 curl -X POST \ localhost:8080/auth/realms/test-realm/protocol/openid-connect/… \ -H 'Content-Type: application/x-www-form-urlencoded' \ -H 'Postman-Token: 90787d63-46e4-4da0-a464-c7094a5b27e7' \ -H 'cache-control: no-cache' \ -d 'grant_type=password&client_id=postman-client&password=112&scope=openid%20email%20profile&username=test-admin'

以上是关于使用 KeycloakAutoConfiguration 无法使用 Spring Boot Security UnsatisfiedDependencyException 设置 Keycloak的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)