Docker(Spring Boot 或 Thorntail)和 Keycloak
Docker (Spring Boot or Thorntail) and Keycloak
我有一个问题 运行 Spring Boot 和 Keycloak 都在 docker 容器中。
我开始使用 Keycloak mysql 作为 docker 中的数据库 运行。
services:
mysql:
image: mysql:5.7
container_name: mysql
volumes:
- mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: keycloak
MYSQL_USER: keycloak
MYSQL_PASSWORD: password
networks:
- testNetwork
keycloak:
image: jboss/keycloak
container_name: keycloak
restart: on-failure
volumes:
- ./config:/config/
environment:
DB_VENDOR: MYSQL
DB_ADDR: mysql
DB_DATABASE: keycloak
DB_USER: keycloak
DB_PASSWORD: password
KEYCLOAK_USER: xxx
KEYCLOAK_PASSWORD: yyy
KEYCLOAK_IMPORT_REALM: /keycloak/import/realm-import.json
ports:
- 8180:8080
depends_on:
- mysql
networks:
- testNetwork
然后我添加了我的领域 (SpringBootKeycloak)、我的客户端 (testclient) 和一个角色为 'user' 的用户。
之后,我将 spring-security 添加到我的 Spring-boot-application。并编辑了我的 application.yml
spring:
main:
banner-mode: 'off'
application:
name: testclient
version: @project.version@
jpa:
hibernate:
ddl-auto: create
datasource:
url: jdbc:h2:mem:testclient;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: xxx
password: xxx
keycloak:
auth-server-url: http://localhost:8180/auth
realm: SpringBootKeycloak
resource: testclient
public-client: true
principal-attribute: preferred_username
security-constraints:
- authRoles:
- user
securityCollections:
- patterns:
- /*
server:
port: ${port:8090}
rest:
path: testclient
据此我添加了我的安全配置:
/**
* Secure appropriate endpoints
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/*").hasRole("user") // only user with role user are allowed to access
.anyRequest().permitAll();
}
运行 我的 Spring 本地启动应用程序工作正常。
我必须使用 keycloak 登录并重定向到 localhost:8090。
但是当我将我的 SpringBoot-Application 添加到我的 docker-compose 并在容器中启动它时,我仍然使用 keycloak 进行登录,但是当我应该重定向时我得到一个 403.
testclient:
image: testclient
container_name: testclient
environment:
JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n"
build:
context: testclient-application
ports:
- 8090:8090
- 5006:5005
networks:
- testNetwork
具有以下容器日志:
{"@timestamp":"2018-08-16T11:50:11.530+00:00","@version":"1","message":"failed to turn code into token","logger_name":"org.keycloak.adapters.OAuthRequestAuthenticator","thread_name":"http-nio-8090-exec-6","level":"ERROR","level_value":40000,"stack_trace":"java.net.ConnectException: Connection refused (Connection refused)\n\tat java.net.PlainSocketImpl.socketConnect(Native Method)\n\tat java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)\n\tat java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)\n\tat java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)\n\tat java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)\n\tat java.net.Socket.connect(Socket.java:589)\n\tat org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:121)\n\tat org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)\n\tat org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:144)\n\tat org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:134)\n\tat org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:610)\n\tat org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:445)\n\tat org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835)\n\tat org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)\n\tat org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)\n\tat org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)\n\tat org.keycloak.adapters.ServerRequest.invokeAccessCodeToToken(ServerRequest.java:111)\n\tat org.keycloak.adapters.OAuthRequestAuthenticator.resolveCode(OAuthRequestAuthenticator.java:336)\n\tat org.keycloak.adapters.OAuthRequestAuthenticator.authenticate(OAuthRequestAuthenticator.java:281)\n\tat org.keycloak.adapters.RequestAuthenticator.authenticate(RequestAuthenticator.java:139)\n\tat org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.authenticateInternal(AbstractKeycloakAuthenticatorValve.java:203)\n\tat org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve.authenticate(KeycloakAuthenticatorValve.java:50)\n\tat org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve.doAuthenticate(KeycloakAuthenticatorValve.java:57)\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:575)\n\tat org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800)\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.lang.Thread.run(Thread.java:748)\n","app":"testclient","version":"1.0.0-SNAPSHOT"}
我不知道如何解决这个...
编辑 1:
还有一条信息:我在 Windows.
运行 docker
编辑 2:解决方案
我的工作解决方案包含以下内容:
- 步骤,添加keycloak作为主机
To make things work, you’ll need to make sure to add the following to your hosts file (/etc/hosts on Mac/Linux, c:\Windows\System32\Drivers\etc\hosts on Windows).
127.0.0.1 keycloak
This is because you will access your application with a browser on your machine (which name is localhost, or 127.0.0.1), but inside Docker it will run in its own container, which name is keycloak.
- 步骤
内部Docker端口和发布端口需要相同:
services:
mysql:
image: mysql:5.7
container_name: mysql
volumes:
- mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: keycloak
MYSQL_USER: keycloak
MYSQL_PASSWORD: password
networks:
- testNetwork
keycloak:
image: jboss/keycloak
container_name: keycloak
restart: on-failure
volumes:
- ./config:/config/
environment:
DB_VENDOR: MYSQL
DB_ADDR: mysql
DB_DATABASE: keycloak
DB_USER: keycloak
DB_PASSWORD: password
KEYCLOAK_USER: xxx
KEYCLOAK_PASSWORD: yyy
KEYCLOAK_IMPORT_REALM: /keycloak/import/realm-import.json
ports:
- 8080:8080 <--- edited
depends_on:
- mysql
networks:
- testNetwork
第 3 步:application.yml 中的 keycloak 定义,用于 Spring boot edited auth-server-url:
keycloak:
realm: SpringBootKeycloak
auth-server-url: http://keycloak:8080/auth <--- edited
resource: testclient
public-client: true
security-constraints:
- authRoles:
- user
securityCollections:
- patterns:
- /*
ssl-required: external
confidential-port: 0
此解决方案带来的丑陋之处:
您不能将 Docker 端口映射到另一个端口以从 url 访问。
端口:
- 8080:8080
我花了很多时间测试其他组合,结果是访问 url 端口必须与内部 docker 端口相同(在我的例子中是 8080)。
编辑 4:
Thorntail 也同样如此。
要更改 Keycloak 的端口添加...
environment:
JAVA_OPTS: "-Djboss.socket.binding.port-offset=10 -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m
-Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true"
... docker-compose 中的 keycloak。
-Djboss.socket.binding.port-offset=10 设置默认端口 (8080) + 偏移量 (10)
其余的是 keycloak 的默认值。
不要忘记编辑 "ports" 和 "auth-server-url"
我认为你的问题是auth-server-url: http://localhost:8180/auth
。当您的应用程序位于 docker 容器内 运行 时,localhost
实际上具有不同的含义。
在容器内部,它需要是容器的名称,即 keycloak
。这有点尴尬,因为当您从主机连接到 keycloak 时,您想要使用 localhost
但令牌发行者 url 需要与令牌所在的 url 相匹配请求(否则令牌被拒绝)所以你最终不得不将 keycloak
放入你的 etc/hosts 文件中。
你很好地解决了这个问题 - 我遇到过这个 working with Activiti. And you can find the JHipster project dealing with it in the same way - 他们说:
To make things work, you’ll need to make sure to add the following to your hosts file (/etc/hosts
on Mac/Linux, c:\Windows\System32\Drivers\etc\hosts
on Windows).
127.0.0.1 keycloak
This is because you will access your application with a browser on your machine (which name is localhost
, or 127.0.0.1
), but inside Docker it will run in its own container, which name is keycloak
.
感谢您的提问和回答!我为此苦苦挣扎了一段时间,并收到连接被拒绝的错误。原因是因为我正在映射 8180:8080,一旦我映射 8080:8080 一切都开始工作了!再次感谢!
我有一个问题 运行 Spring Boot 和 Keycloak 都在 docker 容器中。
我开始使用 Keycloak mysql 作为 docker 中的数据库 运行。
services:
mysql:
image: mysql:5.7
container_name: mysql
volumes:
- mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: keycloak
MYSQL_USER: keycloak
MYSQL_PASSWORD: password
networks:
- testNetwork
keycloak:
image: jboss/keycloak
container_name: keycloak
restart: on-failure
volumes:
- ./config:/config/
environment:
DB_VENDOR: MYSQL
DB_ADDR: mysql
DB_DATABASE: keycloak
DB_USER: keycloak
DB_PASSWORD: password
KEYCLOAK_USER: xxx
KEYCLOAK_PASSWORD: yyy
KEYCLOAK_IMPORT_REALM: /keycloak/import/realm-import.json
ports:
- 8180:8080
depends_on:
- mysql
networks:
- testNetwork
然后我添加了我的领域 (SpringBootKeycloak)、我的客户端 (testclient) 和一个角色为 'user' 的用户。 之后,我将 spring-security 添加到我的 Spring-boot-application。并编辑了我的 application.yml
spring:
main:
banner-mode: 'off'
application:
name: testclient
version: @project.version@
jpa:
hibernate:
ddl-auto: create
datasource:
url: jdbc:h2:mem:testclient;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: xxx
password: xxx
keycloak:
auth-server-url: http://localhost:8180/auth
realm: SpringBootKeycloak
resource: testclient
public-client: true
principal-attribute: preferred_username
security-constraints:
- authRoles:
- user
securityCollections:
- patterns:
- /*
server:
port: ${port:8090}
rest:
path: testclient
据此我添加了我的安全配置:
/**
* Secure appropriate endpoints
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/*").hasRole("user") // only user with role user are allowed to access
.anyRequest().permitAll();
}
运行 我的 Spring 本地启动应用程序工作正常。 我必须使用 keycloak 登录并重定向到 localhost:8090。 但是当我将我的 SpringBoot-Application 添加到我的 docker-compose 并在容器中启动它时,我仍然使用 keycloak 进行登录,但是当我应该重定向时我得到一个 403.
testclient:
image: testclient
container_name: testclient
environment:
JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n"
build:
context: testclient-application
ports:
- 8090:8090
- 5006:5005
networks:
- testNetwork
具有以下容器日志:
{"@timestamp":"2018-08-16T11:50:11.530+00:00","@version":"1","message":"failed to turn code into token","logger_name":"org.keycloak.adapters.OAuthRequestAuthenticator","thread_name":"http-nio-8090-exec-6","level":"ERROR","level_value":40000,"stack_trace":"java.net.ConnectException: Connection refused (Connection refused)\n\tat java.net.PlainSocketImpl.socketConnect(Native Method)\n\tat java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)\n\tat java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)\n\tat java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)\n\tat java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)\n\tat java.net.Socket.connect(Socket.java:589)\n\tat org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:121)\n\tat org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)\n\tat org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:144)\n\tat org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:134)\n\tat org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:610)\n\tat org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:445)\n\tat org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835)\n\tat org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)\n\tat org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)\n\tat org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)\n\tat org.keycloak.adapters.ServerRequest.invokeAccessCodeToToken(ServerRequest.java:111)\n\tat org.keycloak.adapters.OAuthRequestAuthenticator.resolveCode(OAuthRequestAuthenticator.java:336)\n\tat org.keycloak.adapters.OAuthRequestAuthenticator.authenticate(OAuthRequestAuthenticator.java:281)\n\tat org.keycloak.adapters.RequestAuthenticator.authenticate(RequestAuthenticator.java:139)\n\tat org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.authenticateInternal(AbstractKeycloakAuthenticatorValve.java:203)\n\tat org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve.authenticate(KeycloakAuthenticatorValve.java:50)\n\tat org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve.doAuthenticate(KeycloakAuthenticatorValve.java:57)\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:575)\n\tat org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800)\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.lang.Thread.run(Thread.java:748)\n","app":"testclient","version":"1.0.0-SNAPSHOT"}
我不知道如何解决这个...
编辑 1: 还有一条信息:我在 Windows.
运行 docker编辑 2:解决方案
我的工作解决方案包含以下内容:
- 步骤,添加keycloak作为主机
To make things work, you’ll need to make sure to add the following to your hosts file (/etc/hosts on Mac/Linux, c:\Windows\System32\Drivers\etc\hosts on Windows).
127.0.0.1 keycloak
This is because you will access your application with a browser on your machine (which name is localhost, or 127.0.0.1), but inside Docker it will run in its own container, which name is keycloak.
- 步骤
内部Docker端口和发布端口需要相同:
services:
mysql:
image: mysql:5.7
container_name: mysql
volumes:
- mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: keycloak
MYSQL_USER: keycloak
MYSQL_PASSWORD: password
networks:
- testNetwork
keycloak:
image: jboss/keycloak
container_name: keycloak
restart: on-failure
volumes:
- ./config:/config/
environment:
DB_VENDOR: MYSQL
DB_ADDR: mysql
DB_DATABASE: keycloak
DB_USER: keycloak
DB_PASSWORD: password
KEYCLOAK_USER: xxx
KEYCLOAK_PASSWORD: yyy
KEYCLOAK_IMPORT_REALM: /keycloak/import/realm-import.json
ports:
- 8080:8080 <--- edited
depends_on:
- mysql
networks:
- testNetwork
第 3 步:application.yml 中的 keycloak 定义,用于 Spring boot edited auth-server-url:
keycloak:
realm: SpringBootKeycloak
auth-server-url: http://keycloak:8080/auth <--- edited
resource: testclient
public-client: true
security-constraints:
- authRoles:
- user
securityCollections:
- patterns:
- /*
ssl-required: external
confidential-port: 0
此解决方案带来的丑陋之处: 您不能将 Docker 端口映射到另一个端口以从 url 访问。 端口: - 8080:8080 我花了很多时间测试其他组合,结果是访问 url 端口必须与内部 docker 端口相同(在我的例子中是 8080)。
编辑 4:
Thorntail 也同样如此。
要更改 Keycloak 的端口添加...
environment:
JAVA_OPTS: "-Djboss.socket.binding.port-offset=10 -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m
-Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true"
... docker-compose 中的 keycloak。 -Djboss.socket.binding.port-offset=10 设置默认端口 (8080) + 偏移量 (10) 其余的是 keycloak 的默认值。 不要忘记编辑 "ports" 和 "auth-server-url"
我认为你的问题是auth-server-url: http://localhost:8180/auth
。当您的应用程序位于 docker 容器内 运行 时,localhost
实际上具有不同的含义。
在容器内部,它需要是容器的名称,即 keycloak
。这有点尴尬,因为当您从主机连接到 keycloak 时,您想要使用 localhost
但令牌发行者 url 需要与令牌所在的 url 相匹配请求(否则令牌被拒绝)所以你最终不得不将 keycloak
放入你的 etc/hosts 文件中。
你很好地解决了这个问题 - 我遇到过这个 working with Activiti. And you can find the JHipster project dealing with it in the same way - 他们说:
To make things work, you’ll need to make sure to add the following to your hosts file (
/etc/hosts
on Mac/Linux,c:\Windows\System32\Drivers\etc\hosts
on Windows).
127.0.0.1 keycloak
This is because you will access your application with a browser on your machine (which name is
localhost
, or127.0.0.1
), but inside Docker it will run in its own container, which name iskeycloak
.
感谢您的提问和回答!我为此苦苦挣扎了一段时间,并收到连接被拒绝的错误。原因是因为我正在映射 8180:8080,一旦我映射 8080:8080 一切都开始工作了!再次感谢!