Ogrtač za ključeve ugrađen u aplikaciju za proljetno pokretanje

1. Pregled

Keycloak je rješenje za upravljanje identitetom i pristupom otvorenog koda upravlja RedHat, a na Javi razvija JBoss.

U ovom uputstvu naučit ćemo kako postaviti poslužitelj Keycloak ugrađen u aplikaciju Spring Boot. To olakšava pokretanje unaprijed konfiguriranog poslužitelja Keycloak.

Keycloak se također može pokrenuti kao samostalni poslužitelj, ali tada uključuje njegovo preuzimanje i postavljanje putem Admin Consolea.

2. Predkonfiguracija ogrtača

Za početak, shvatimo kako možemo unaprijed konfigurirati poslužitelj Keycloak.

Poslužitelj sadrži skup područja, pri čemu svako područje djeluje kao izolirana jedinica za upravljanje korisnicima. Da bismo je prethodno konfigurirali, moramo navesti datoteku definicije područja u JSON formatu.

Sve što se može konfigurirati pomoću administratorske konzole Keycloak zadržalo se u ovom JSON-u.

Naš će autorizacijski poslužitelj biti unaprijed konfiguriran sa baeldung-carstvo.json. Pogledajmo nekoliko relevantnih konfiguracija u datoteci:

  • korisnika: naši zadani korisnici bili bi [e-pošta zaštićena] i [e-pošta zaštićena]; ovdje će imati i svoje vjerodajnice
  • klijentima: definirat ćemo klijenta s id-om newClient
  • standardFlowEnabled: postavljeno na true za aktiviranje tijeka autorizacijskog koda za newClient
  • preusmjeravanjeUris: newClientOvdje su navedeni URL-ovi na koje će poslužitelj preusmjeriti nakon uspješne provjere autentičnosti
  • webOrigins: postavljen “+” kako bi se omogućila CORS podrška za sve URL-ove navedene kao preusmjeravanjeUris

Poslužitelj Keycloak prema zadanim postavkama izdaje JWT tokene, pa za to nije potrebna posebna konfiguracija. Pogledajmo dalje konfiguracije Mavena.

3. Konfiguracija Mavena

Budući da ćemo Keycloak ugraditi u aplikaciju Spring Boot, nema potrebe za zasebnim preuzimanjem.

Umjesto toga, postavit ćemo sljedeći skup ovisnosti:

 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-aktuator org.springframework.boot spring-boot-starter-data-jpa com.h2database h2 runtime 

Imajte na umu da ovdje koristimo verziju 2.2.6.RELEASE Spring Boota. Ovisnosti spring-boot-starter-data-jpa i H2 dodani su za trajnost. Drugi opružni okvir.pokretanje ovisnosti su za web podršku, jer također trebamo biti u mogućnosti pokrenuti Keycloak autorizacijski poslužitelj, kao i administratorsku konzolu kao web usluge.

Trebat će nam i nekoliko ovisnosti za Keycloak i RESTEasy:

 org.jboss.resteasy resteasy-jackson2-provider 3.12.1.Final org.keycloak keycloak-dependencies-server-all 11.0.2 pom 

Na web mjestu Maven potražite najnovije verzije Keycloak-a i RESTEasy-a.

I na kraju, moramo nadjačati za korištenje verzije koju je deklarirao Keycloak umjesto one koju je definirao Spring Boot:

 10.1.8.Finale 

4. Konfiguracija ugrađenog ključa

Sada definirajmo Spring konfiguraciju za naš autorizacijski poslužitelj:

Javna klasa @Configuration EmbeddedKeycloakConfig {@Bean ServletRegistrationBean keycloakJaxRsApplication (KeycloakServerProperties keycloakServerProperties, DataSource dataSource) baca izuzetak {mockJndiEnvironment (dataSource); EmbeddedKeycloakApplication.keycloakServerProperties = keycloakServerProperties; ServletRegistrationBean servlet = novi ServletRegistrationBean (novi HttpServlet30Dispatcher ()); servlet.addInitParameter ("javax.ws.rs.Application", EmbeddedKeycloakApplication.class.getName ()); servlet.addInitParameter (ResteasyContextParameters.RESTEASY_SERVLET_MAPPING_PREFIX, keycloakServerProperties.getContextPath ()); servlet.addInitParameter (ResteasyContextParameters.RESTEASY_USE_CONTAINER_FORM_PARAMS, "true"); servlet.addUrlMappings (keycloakServerProperties.getContextPath () + "/ *"); servlet.setLoadOnStartup (1); servlet.setAsyncSupported (true); povratni servlet; } @Bean FilterRegistrationBean keycloakSessionManagement (KeycloakServerProperties keycloakServerProperties) {FilterRegistrationBean filter = novi FilterRegistrationBean (); filter.setName ("Upravljanje sesijama ključa"); filter.setFilter (novi EmbeddedKeycloakRequestFilter ()); filter.addUrlPatterns (keycloakServerProperties.getContextPath () + "/ *"); povratni filter; } private void mockJndiEnvironment (DataSource dataSource) baca NamingException {NamingManager.setInitialContextFactoryBuilder ((env) -> (okolina) -> new InitialContext () {@ Nadjačaj javno traženje objekta (ime)) {return lookup (name.to); } @Override public Object lookup (String name) {if ("spring / datasource" .equals (name)) {return dataSource;} return null;} @Override public NameParser getNameParser (ime niza) {return CompositeName :: new;} @Preuzmi javnu prazninu close () {}}); }} 

Napomena: ne brinite zbog pogreške kompilacije, mi ćemo definirati EmbeddedKeycloakRequestFilter razred kasnije.

Kao što ovdje možemo vidjeti, Keycloak smo prvo konfigurirali kao JAX-RS aplikaciju sa KeycloakServerProperties za trajnu pohranu svojstava Keycloak-a kako je navedeno u našoj datoteci definicije područja. Zatim smo dodali filtar za upravljanje sesijama i ismijali JNDI okruženje da bismo koristili izvor / izvor podataka, koja je naša H2 baza podataka u memoriji.

5. KeycloakServerProperties

Ajmo sada pogledati KeycloakServerProperties upravo smo spomenuli:

@ConfigurationProperties (prefix = "keycloak.server") javna klasa KeycloakServerProperties {String contextPath = "/ auth"; Niz realmImportFile = "baeldung-realm.json"; AdminUser adminUser = novi AdminUser (); // getteri i postavljači javna statička klasa AdminUser {String username = "admin"; Lozinka niza = "admin"; // geteri i postavljači}} 

Kao što vidimo, ovo je jednostavan POJO za postavljanje contextPath, adminUser i datoteka definicije područja.

6. EmbeddedKeycloakApplication

Dalje, pogledajmo klasu koja koristi konfiguracije koje smo prije postavili za stvaranje područja:

javna klasa EmbeddedKeycloakApplication proširuje KeycloakApplication {private static final Logger LOG = LoggerFactory.getLogger (EmbeddedKeycloakApplication.class); statički KeycloakServerProperties keycloakServerProperties; zaštićena praznina loadConfig () {tvornica JsonConfigProviderFactory = nova RegularJsonConfigProviderFactory (); Config.init (factory.create () .orElseThrow (() -> novi NoSuchElementException ("Nema vrijednosti koja postoji"))); } javna EmbeddedKeycloakApplication () {createMasterRealmAdminUser (); createBaeldungRealm (); } privatna praznina createMasterRealmAdminUser () {KeycloakSession session = getSessionFactory (). create (); ApplianceBootstrap applianceBootstrap = novi ApplianceBootstrap (sesija); AdminUser admin = keycloakServerProperties.getAdminUser (); isprobajte {session.getTransactionManager (). begin (); applianceBootstrap.createMasterRealmUser (admin.getUsername (), admin.getPassword ()); session.getTransactionManager (). commit (); } catch (Iznimka ex) {LOG.warn ("Nije moguće stvoriti glavnog administratora korisnika ogrtača ključeva: {}", ex.getMessage ()); session.getTransactionManager (). rollback (); } session.close (); } privatna praznina createBaeldungRealm () {KeycloakSession session = getSessionFactory (). create (); isprobajte {session.getTransactionManager (). begin (); RealmManager manager = novi RealmManager (sesija); Lekcija resursaRealmImportFile = novi ClassPathResource (keycloakServerProperties.getRealmImportFile ()); manager.importRealm (JsonSerialization.readValue (lekcijaRealmImportFile.getInputStream (), RealmRepresentation.class)); session.getTransactionManager (). commit (); } catch (Iznimka ex) {LOG.warn ("Nije uspio uvesti json datoteku Realm: {}", ex.getMessage ()); session.getTransactionManager (). rollback (); } session.close (); }} 

7. Implementacije prilagođene platforme

Kao što smo rekli, Keycloak je razvio RedHat / JBoss. Stoga pruža biblioteke funkcionalnosti i proširenja za postavljanje aplikacije na Wildfly poslužitelj ili kao Quarkus rješenje.

U ovom se slučaju udaljavamo od tih alternativa i kao posljedicu toga moramo pružiti prilagođene implementacije za neka sučelja i klase specifične za platformu.

Na primjer, u EmbeddedKeycloakApplication upravo smo konfigurirali prvo smo učitali konfiguraciju poslužitelja Keycloak-a keycloak-server.json, koristeći praznu potklasu sažetka JsonConfigProviderFactory:

javna klasa RegularJsonConfigProviderFactory proširuje JsonConfigProviderFactory {}

Zatim smo produžili KeycloakApplication stvoriti dva područja: ovladati; majstorski i baeldung. Oni su stvoreni prema svojstvima navedenim u našoj datoteci definicije carstva, baeldung-carstvo.json.

Kao što vidite, koristimo a KeycloakSession da bismo izvršili sve transakcije i da bi ovo ispravno funkcioniralo, morali smo stvoriti običaj AbstractRequestFilter (EmbeddedKeycloakRequestFilter) i za to postavite grah pomoću a KeycloakSessionServletFilter u EmbeddedKeycloakConfig datoteka.

Uz to, trebamo nekoliko prilagođenih davatelja usluga tako da imamo vlastite implementacije org.keycloak.common.util.ResteasyProvider i org.keycloak.platform.PlatformProvider i ne oslanjaju se na vanjske ovisnosti.

Važno je da se podaci o tim prilagođenim pružateljima usluga trebaju uključiti u projekt META-INF / usluge mapu tako da se pokupe tijekom izvođenja.

8. Sve to zajedno

Kao što smo vidjeli, Keycloak je znatno pojednostavio potrebne konfiguracije sa strane aplikacije. Nije potrebno programski definirati izvor podataka niti bilo kakve sigurnosne konfiguracije.

Da bismo sve to skupili, moramo definirati konfiguraciju za Spring i Spring Boot Application.

8.1. primjena.iml

Za konfiguracije Spring koristit ćemo jednostavan YAML:

poslužitelj: port: 8083 proljeće: izvor podataka: korisničko ime: sa url: jdbc: h2: mem: testdb keycloak: server: contextPath: / auth adminUser: korisničko ime: bael-admin lozinka: ******** realmImportFile: baeldung- carstvo.json

8.2. Primjena za proljetno pokretanje

I na kraju, evo Proljetne aplikacije za pokretanje:

@SpringBootApplication (exclude = LiquibaseAutoConfiguration.class) @EnableConfigurationProperties (KeycloakServerProperties.class) javna klasa AuthorizationServerApp {private static final Logger LOG = LoggerFactory.getLogger (AuthorizationServerApp.class; javna statička void glavna (String [] args) baca iznimku {SpringApplication.run (AuthorizationServerApp.class, args); } @Bean ApplicationListener onApplicationReadyEventListener (ServerProperties serverProperties, KeycloakServerProperties keycloakServerProperties) {return (evt) -> {Integer port = serverProperties.getPort (); Niz keycloakContextPath = keycloakServerProperties.getContextPath (); LOG.info ("Ugrađeni ključni ogrtač pokrenut: // localhost: {} {} za upotrebu ogrtača ključeva", port, keycloakContextPath); }; }}

Značajno, ovdje smo omogućili KeycloakServerProperties konfiguracija za ubrizgavanje u ApplicationListener grah.

Nakon pokretanja ove nastave, pristupnoj stranici poslužitelja za autorizaciju možemo pristupiti na // localhost: 8083 / auth /.

9. Zaključak

U ovom smo brzom vodiču vidjeli kako postaviti poslužitelj Keycloak ugrađen u aplikaciju Spring Boot. Izvorni kod za ovu aplikaciju dostupan je na GitHub-u.

Izvornu ideju za ovu implementaciju razvio je Thomas Darimont i može se naći u projektu embedded-spring-boot-keycloak-server.