Java >> Java Tutorial >  >> Tag >> Spring

Der endgültige Leitfaden zur Verwendung von Keycloak mit einer Spring Boot-Anwendung

In diesem Beitrag werde ich zeigen, wie man Keycloak in einer Spring Boot-Anwendung verwendet. Bevor wir Keycloak verwenden, werden wir einige Grundlagen darüber behandeln, was Keycloak ist und warum wir es verwenden.

Um mit dieser Demo zu beginnen, benötigen Sie die folgenden Dinge:

  • Ein Code-Editor – IntelliJ
  • Datenbank – MySQL
  • Schlüsselumhang
  • Java 8

Was ist Keycloak?

Keycloak ist eine Open-Source-Identitäts- und Zugriffsverwaltungslösung für moderne Anwendungen und Dienste. Keycloak bietet sowohl SAML- als auch OpenID-Protokolllösungen.

Warum verwenden wir Keycloak?

Wie bereits erwähnt, bietet Keycloak Identitäts- und Zugriffsverwaltung, es ist auch Open Source. SAML- und OpenID-Protokolle sind Industriestandards. Das Erstellen einer Anwendung, die in Keycloak integriert ist, bietet Ihnen nur eine sicherere und stabilere Lösung. Es gibt definitiv andere Lösungen wie Gluu, Shibboleth, WSO2 und Okta.

Für diesen Beitrag verwenden wir Keycloak.

Spring Boot-Anwendung mit Keycloak sichern

Diese Demo besteht aus zwei Teilen. Einer handelt von Keycloak. Die zweite betrifft das Sichern der Spring Boot-Anwendung mit Keycloak.

Keycloak installieren

Laden Sie den Keyclon auf Ihren Computer herunter. Entpacken Sie die heruntergeladene Datei und führen Sie den Server mit dem folgenden Befehl aus dem bin-Verzeichnis an Ihrer Eingabeaufforderung aus (Hinweis – ich arbeite auf einem Windows-Computer):

standalone.bat -Djboss.socket.binding.port-offset=100

Dadurch wird Wildfly gestartet Server für Ihr Keycloak auf Ihrem lokalen Rechner. Wir können auf den Server zugreifen, indem wir die URL http://localhost:8180 ausführen . Wenn Sie nur standalone.bat verwenden ohne diesen Parameter auszuführen, wird der Server auf dem Port 8080 ausgeführt .

Sobald Sie den Server gestartet haben, müssen Sie als Erstes einen Admin-Benutzer erstellen. Wir erstellen einen Benutzer admin und Passwort d#n3q2b .

Jetzt greifen wir auf die Verwaltungskonsole zu und geben unsere Benutzerdaten ein. Sobald wir uns als admin anmelden Benutzer, sehen wir den ersten Bildschirm wie folgt:

Anwendung hinzufügen

Anfangsbildschirme zeigen den Standardbereich. Für unsere Demozwecke erstellen wir einen neuen Realm SpringBootKeycloakApp . In diesem Bereich fügen wir unsere Spring Boot-Anwendung als Client hinzu. Erstellen Sie einen neuen Kunden auf der Registerkarte Kunden. Wir nennen unsere Client-Anwendung SpringBootApp .

Jetzt fügen wir in den Einstellungen redirect url hinzu für unsere Spring Boot-Anwendung. Dies ist die URL, über die Keycloak nach der Authentifizierung zu unserer App umleitet. Außerdem verwenden wir openid connect als Protokoll als Teil dieser Implementierung.

Benutzer hinzufügen

Jetzt fügen wir einen Benutzer hinzu, den wir zur Authentifizierung verwenden. Wir werden diesen Benutzer verwenden, um uns bei unserer Spring Boot-Beispielanwendung anzumelden.

Fügen Sie eine gewünschte Rolle für diesen Benutzer ROLE_User hinzu auf der Registerkarte Rollen in Keycloak. Sobald dies erledigt ist, gehen wir zur Registerkarte Benutzer und fügen einen neuen Benutzer hinzu.

Auf der Role Mappings Stellen Sie sicher, dass Sie die neu erstellte Rolle für diesen Benutzer hinzufügen.

Erstellen Sie eine Spring Boot-Anwendung

Jetzt erstellen wir eine einfache Spring Boot-Anwendung, die Keycloak für die Sicherheit verwendet. Als Teil dieser Anwendung zeigen wir dem Benutzer, der sich bei der Anwendung authentifiziert, eine Liste mit To-Do-Listen-Aufgaben.

Um diese App zu erstellen, benötigen wir die folgenden Abhängigkeiten:


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'
}

Wie Sie sehen können, verwenden wir spring-boot und spring-security zusammen mit keycloak-spring-boot-starter Abhängigkeit.

Die keycloak Abhängigkeit umfasst Keycloak-Client-Adapter. Wir verwenden diese Adapter für Authentifizierungszwecke. Sie ersetzen unsere standardmäßigen Spring Security-Adapter. Um dies sicherzustellen keycloak-spring-boot-starter Abhängigkeit korrekt funktioniert, benötigen wir eine weitere Abhängigkeit, die in unserer Gradle-Datei wie folgt hinzugefügt werden muss:


dependencyManagement {
	imports {
		mavenBom "org.keycloak.bom:keycloak-adapter-bom:11.0.2"
	}
}

Um mehr darüber zu erfahren, können Sie die offizielle Dokumentation von keycloak besuchen.

Unsere Controller-Klasse verfügt über zwei wichtige Methoden, eine zum Abrufen der Homepage, auf die jeder zugreifen kann, und eine andere zum Abrufen der Liste der Aufgaben, auf die nur authentifizierte Benutzer mit einer Rolle ROLE_User zugreifen können . Der Code für diesen TaskController wird wie folgt aussehen:


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());
    }

}

In dieser Controller-Klasse verwenden wir TaskManager um alle Aufgaben zu bekommen. Ich werde  KeyCloakSecurityContext erklären wenn ich über SecurityConfig zeige .

Mit oder ohne Spring-Security

Wir können diese Anwendung nutzen und Keycloak für die Authentifizierung mit oder ohne Spring-Security verwenden . Als Teil dieser Demo verwenden wir Spring-Security . Um dieselbe Anwendung ohne Spring-Security zu verwenden , können Sie einfach den Spring-Security entfernen Abhängigkeit und fügen Sie die Sicherheitskonfiguration durch application.properties hinzu Datei.

Wir benötigen die folgenden Eigenschaften in application.properties um Keycloak für die Authentifizierung in dieser App zu verwenden.

keycloak.auth-server-url=http://localhost:8180/auth
keycloak.realm=SpringBootKeycloakApp
keycloak.resource=SpringBootApp
keycloak.public-client=true
keycloak.principal-attribute=preferred_username

Wenn wir diese Anwendung ohne Spring-Security verwenden möchten, benötigen wir auch die folgenden zwei Eigenschaften:

keycloak.security-constraints[0].authRoles[0]=ROLE_User
keycloak.security-constraints[0].securityCollections[0].patterns[0]=/tasks

Da wir Spring-Security verwenden, konfigurieren wir die Sicherheitskonfiguration über eine Java-Klasse SecurityConfig .

Dieser SecurityConfig Klasse erweitert KeyCloakWebSecurityConfigurerAdapter .

Unser configure Methode sieht wie folgt aus:

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception
    {
        super.configure(httpSecurity);
        httpSecurity.authorizeRequests()
                .antMatchers("/tasks").hasRole("User")
                .anyRequest().permitAll();
    }

Grundsätzlich alle Anfragen, die an /tasks kommen Endpunkt, sollte die Benutzerrolle ROLE_User haben . Das Präfix von ROLE_ wird hier vorausgesetzt. Andere als jede andere Anfrage ist ohne Genehmigung zulässig. In diesem Fall rufen wir unsere Indexseite auf.

Wir verwenden die Anmerkung @KeyCloakConfiguration was im Wesentlichen @Configuration abdeckt und @EnableWebSecurity Anmerkungen.

Da unser SecurityConfig erweitert KeycloakWebSecurityConfigurerAdapter , müssen wir sessionAuthenticationStrategy implementieren und httpSessionManager . Wir müssen auch unseren IDP Keycloak registrieren mit Spring Security Authentication Manager.

Unsere SecurityConfig sieht also wie folgt aus:


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();
    }
}

Daher verwendet Spring Security Rollen in Großbuchstaben wie ROLE_USER und verwendet immer ROLE_ Präfix. Um das zu handhaben, habe ich einen Benutzer mit einer Rolle ROLE_User hinzugefügt in Keycloak, aber wir werden nur ein Präfix überprüfen, da unsere http-Konfiguration die Rolle sowieso überprüfen wird.

Da wir uns mit Keycloak authentifizieren, benötigen wir eine Sitzung für den Status des Benutzers. Wir verwenden RegisterSessionAuthenticationStrategy hier. HttpSessionManager ist eine bedingte Bean, da Keycloak diese Bean bereits implementiert.

Um den Keycloak Spring Boot-Adapter zu implementieren, fügen wir eine KeyCloakSpringBootConfigResolver-Bean wie folgt hinzu:


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();
    }
}

Ich habe den Rest des Anwendungsaufbaus nicht gezeigt, aber der Code für dieses Projekt ist auf GitHub verfügbar.

Demo der Anwendung

Führen Sie unsere Keycloak-Anwendung aus, sie wird auf http://localhost:8180 ausgeführt . Unsere Spring Boot-Anwendung wird unter http://localhost:8080 ausgeführt .

Unser erster Bildschirm der Spring Boot-Anwendung sieht wie folgt aus:

Wenn ein Benutzer jetzt auf Get all tasks klickt , wird er wie folgt zum Anmeldebildschirm von Keycloak weitergeleitet:

Jetzt gebe ich meinen User betterjavacode-Benutzernamen und mein Passwort ein und es zeigt uns unsere Aufgabenliste wie folgt:

Authentifizierungsablauf

Wenn der Benutzer auf Get all tasks klickt , wird der Benutzer zu sso/login von Spring Security umgeleitet Endpunkt, den KeycloakSpringBootConfigResolver verarbeitet und eine Autorisierungscodeflussanforderung an Keycloak

sendet

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 verarbeitet die Anfrage, antwortet mit einem Sitzungscode und zeigt den Anmeldebildschirm an.

Sobald der Benutzer Anmeldeinformationen eingibt und Keycloak diese validiert, antwortet es mit einem Autorisierungscode, und dieser Code wird gegen ein Token ausgetauscht, und der Benutzer wird angemeldet.

Schlussfolgerung

In diesem Beitrag habe ich gezeigt, wie Sie Ihre Spring Boot-Anwendung mit Keycloak als Identitätsanbieter sichern können. Wenn Ihnen dieser Beitrag gefallen hat, ziehen Sie bitte in Betracht, meinen Blog hier zu abonnieren.

Referenzen

  1. Schlüsselumhang – Schlüsselumhang
  2. Sichern Ihrer Anwendung mit Keycloak – Sichern Sie Ihre Anwendung

Java-Tag