Spring?Boot應用程序中如何使用Keycloak詳解
正文
在這篇文章中,我將展示如何在 Spring Boot 應用程序中使用 Keycloak。在我們使用 Keycloak 之前,我們將介紹一些關于 Keycloak 是什么以及我們?yōu)槭裁词褂盟幕A知識。
要開始前,您需要具備以下條件:
- 代碼編輯器——IntelliJ
- 數(shù)據(jù)庫——MySQL
- Keycloak
- Java 8
什么是Keycloak?
Keycloak是一種用于現(xiàn)代應用程序和服務的開源身份和訪問管理解決方案。Keycloak 同時提供 SAML 和 OpenID 協(xié)議解決方案。
我們?yōu)槭裁匆褂肒eycloak?
如前所述,Keycloak 提供身份和訪問管理,它也是開源的。SAML 和 OpenID 協(xié)議是行業(yè)標準。構建與 Keycloak 集成的應用程序只會為您提供更安全和穩(wěn)定的解決方案。當然還有其他可用的解決方案,如 Gluu、Shibboleth、WSO2。
對于這篇文章,我們將使用 Keycloak。
在Spring Boot 應用程序中使用keycloak
這個演示有兩個部分。一個是關于Keycloak。第二個是關于使用 Keycloak 保護 Spring Boot 應用程序。
安裝Keycloak
在您的機器上下載Keycloak 。解壓縮下載的文件并使用命令提示符下 bin 目錄中的以下命令運行服務器(注意 – 我在 Windows 機器上):
standalone.bat -Djboss.socket.binding.port-offset=100
這將在本地計算機上為您的 Keycloak 啟動 Wildfly 服務器。我們可以通過執(zhí)行 URL 來訪問服務器http://localhost:8180。如果您只是使用 standalone.bat 執(zhí)行而沒有該參數(shù),則服務器將在端口上運行8080。

啟動服務器后,您要做的第一件事就是創(chuàng)建一個管理員用戶。我們將創(chuàng)建一個用戶 admin 和密碼 d#n3q2b 。
現(xiàn)在我們將訪問管理控制臺并輸入我們的用戶詳細信息。一旦我們以管理員用戶身份登錄,我們將看到如下第一個屏幕:

添加應用程序
初始屏幕顯示默認領域。出于演示目的,我們將創(chuàng)建一個新領域SpringBootKeycloakApp。在這個領域中,我們將添加我們的 Spring Boot 應用程序作為客戶端。在“客戶端”選項卡上創(chuàng)建一個新客戶端。我們將我們的客戶端應用程序命名為 SpringBootApp。
現(xiàn)在在設置中,我們將為我們的 Spring Boot 應用程序添加重定向 url。這是 Keycloak 將在身份驗證后重定向到我們的應用程序的 URL。此外,我們使用 openid connect 作為協(xié)議作為此實現(xiàn)的一部分。

添加用戶
現(xiàn)在我們將添加一個我們將用于身份驗證的用戶。我們將使用此用戶登錄到我們的示例 Spring Boot 應用程序。
在 Keycloak 的角色選項卡上為該用戶添加您想要的角色ROLE_User。完成后,讓我們轉到“用戶”選項卡并添加一個新用戶。

在 Role Mappings 選項卡上,確保為該用戶添加新創(chuàng)建的角色。
創(chuàng)建 Spring Boot 應用程序
現(xiàn)在,我們將創(chuàng)建一個簡單的 Spring Boot 應用程序,它將使用 Keycloak 來確保安全。作為此應用程序的一部分,我們將為將通過應用程序進行身份驗證的用戶顯示待辦事項列表任務。
要構建此應用程序,我們需要以下依賴項:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.keycloak:keycloak-spring-boot-starter'
runtimeOnly 'mysql:mysql-connector-java'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation 'org.springframework.security:spring-security-test'
}
如您所見,我們正在使用spring-bootandspring-security以及keycloak-spring-boot-starter依賴項。
keycloak 依賴項包括 Keycloak 客戶端適配器。我們將使用這些適配器進行身份驗證。它們將取代我們的標準 Spring Security 適配器。為了確保此keycloak-spring-boot-starter依賴項正常工作,我們需要在我們的 gradle 文件中添加一個依賴項,如下所示:
dependencyManagement {
imports {
mavenBom "org.keycloak.bom:keycloak-adapter-bom:11.0.2"
}
}
要了解更多相關信息,您可以訪問keycloak的官方文檔。
我們的 Controller 類將有兩個重要的方法,一個是獲取任何人都可以訪問的主頁,另一個是獲取任務列表,只有具有 ROLE_User 角色的經(jīng)過身份驗證的用戶才能訪問這些任務。此 TaskController 的代碼如下所示:
package com.betterjavacode.keycloakdemo.keycloakdemo.controllers;
import com.betterjavacode.keycloakdemo.keycloakdemo.dto.TaskDto;
import com.betterjavacode.keycloakdemo.keycloakdemo.managers.TaskManager;
import org.keycloak.KeycloakSecurityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Controller
public class TaskController
{
private final HttpServletRequest request;
@Autowired
public TaskController(HttpServletRequest request)
{
this.request = request;
}
@Autowired
private TaskManager taskManager;
@GetMapping(value="/")
public String home()
{
return "index";
}
@GetMapping(value="/tasks")
public String getTasks(Model model)
{
List tasks = taskManager.getAllTasks();
model.addAttribute("tasks", tasks);
model.addAttribute("name", getKeycloakSecurityContext().getIdToken().getGivenName());
return "tasks";
}
private KeycloakSecurityContext getKeycloakSecurityContext()
{
return (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
}
}
在這個控制器類中,我們用來TaskManager獲取所有任務。我會解釋 KeyCloakSecurityContext我什么時候會展示SecurityConfig。
有沒有使用Spring-Security
我們可以利用此應用程序并使用 Keycloak 進行身份驗證,無論是否使用Spring-Security. 作為本演示的一部分,我們使用Spring-Security. 要在沒有 Spring-Security 的情況下使用相同的應用程序,您只需刪除 Spring-Security 依賴并通過application.properties文件添加安全配置。
我們需要以下屬性才能application.properties在此應用程序中使用 Keycloak 進行身份驗證。
keycloak.auth-server-url=http://localhost:8180/auth keycloak.realm=SpringBootKeycloakApp keycloak.resource=SpringBootApp keycloak.public-client=true keycloak.principal-attribute=preferred_username
如果我們想在沒有 Spring-Security 的情況下使用這個應用程序,我們還需要以下兩個屬性:
keycloak.security-constraints[0].authRoles[0]=ROLE_User keycloak.security-constraints[0].securityCollections[0].patterns[0]=/tasks
由于我們正在使用Spring-Security,所以我們將通過一個 Java 類來配置安全配置SecurityConfig。
這個 SecurityConfig 類將擴展KeyCloakWebSecurityConfigurerAdapter.
我們的配置方法如下所示:
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
super.configure(httpSecurity);
httpSecurity.authorizeRequests()
.antMatchers("/tasks").hasRole("User")
.anyRequest().permitAll();
}
基本上任何到達 /tasks 端點的請求都應該具有 ROLE_User 用戶角色。此處假定 ROLE_ 的前綴。除任何其他請求外,未經(jīng)任何授權將被允許。在這種情況下,我們將調(diào)用我們的索引頁面。
我們將使用@KeyCloakConfiguration基本上是封面@Configuration和@EnableWebSecurity注釋的注釋。
由于我們的SecurityConfigextends KeycloakWebSecurityConfigurerAdapter,我們必須實施 sessionAuthenticationStrategy 和 httpSessionManager 。我們還必須使用 Spring Security Authentication Manager 注冊我們的 idp Keycloak。
所以我們的 SecurityConfig 將如下所示:
package com.betterjavacode.keycloakdemo.keycloakdemo.config;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.keycloak.adapters.springsecurity.management.HttpSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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;
@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
{
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder)
{
SimpleAuthorityMapper simpleAuthorityMapper = new SimpleAuthorityMapper();
simpleAuthorityMapper.setPrefix("ROLE_");
KeycloakAuthenticationProvider keycloakAuthenticationProvider =
keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(simpleAuthorityMapper);
authenticationManagerBuilder.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy ()
{
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
@Override
@ConditionalOnMissingBean(HttpSessionManager.class)
protected HttpSessionManager httpSessionManager()
{
return new HttpSessionManager();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
super.configure(httpSecurity);
httpSecurity.authorizeRequests()
.antMatchers("/tasks").hasRole("User")
.anyRequest().permitAll();
}
}
所以 Spring Security 使用像 ROLE_USER 這樣大寫的角色,并且總是使用 ROLE_ 前綴。為了處理這個問題,我在 Keycloak 中添加了一個角色為 ROLE_User 的用戶,但我們只會驗證一個前綴,因為我們的 http 配置無論如何都會驗證該角色。
由于我們將使用 Keycloak 進行身份驗證,因此我們需要一個用于用戶狀態(tài)的會話。我們在這里使用RegisterSessionAuthenticationStrategy。HttpSessionManager是一個條件 bean,因為 Keycloak 已經(jīng)實現(xiàn)了那個 bean。
要實現(xiàn) Keycloak Spring Boot 適配器,我們將添加一個KeyCloakSpringBootConfigResolverbean,如下所示:
package com.betterjavacode.keycloakdemo.keycloakdemo.config;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class KeycloakConfig
{
@Bean
public KeycloakSpringBootConfigResolver keycloakSpringBootConfigResolver()
{
return new KeycloakSpringBootConfigResolver();
}
}
應用程序演示
運行我們的 keycloak 應用程序,它將在http://localhost:8180上運行。我們的 Spring Boot 應用程序將在http://localhost:8080運行。
我們的 Spring Boot 應用程序的第一個屏幕如下所示:

現(xiàn)在,如果用戶點擊獲取所有任務,他將被重定向到 Keycloak 登錄屏幕,如下所示:

現(xiàn)在,我將輸入我的用戶 betterjavacode 用戶名和密碼,它將向我們顯示我們的任務列表,如下所示:

認證流程
當用戶單擊“獲取所有任務”時,用戶將被重定向到 Spring Security 的 sso/login 端點,KeycloakSpringBootConfigResolver 處理該端點并向 Keycloak 發(fā)送授權代碼流請求
http://localhost:8180/auth/realms/SpringBootKeycloakApp/protocol/openid-connect/auth?response_type=code&client_id=SpringBootApp&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fsso%2Flogin&state=70bd4e28-89e6-43b8-8bea-94c6d057a5cf&login=true&scope=openid
Keycloak 將處理請求以響應會話代碼并顯示登錄屏幕。
一旦用戶輸入憑據(jù)并且 keycloak 驗證了這些憑據(jù),它將使用授權代碼進行響應,并將此代碼交換為令牌,然后用戶登錄。
結論
在這篇文章中,展示了如何使用 Keycloak 作為身份提供者來保護您的 Spring Boot 應用程序。這樣 一個簡單的程序就完成了!
以上就是Spring Boot應用程序中如何使用Keycloak詳解的詳細內(nèi)容,更多關于Spring Boot使用Keycloak的資料請關注腳本之家其它相關文章!
相關文章
線程池調(diào)用kafka發(fā)送消息產(chǎn)生的內(nèi)存泄漏問題排查解決
這篇文章主要為大家介紹了線程池調(diào)用kafka發(fā)送消息產(chǎn)生的內(nèi)存泄漏問題排查解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08
Java class文件格式之屬性_動力節(jié)點Java學院整理
在本文中, 主要講解了class文件中的一些屬性。 這些屬性可以出現(xiàn)在class文件中的對個地方, 用來描述一些其他信息2017-06-06

