Jednostavna jednostruka prijava s Spring Security OAuth2

1. Pregled

U ovom uputstvu razgovarat ćemo o načinu primjene SSO - Single Sign On - pomoću Spring Security OAuth i Spring Boot, koristeći Keycloak kao Autorizacijski poslužitelj.

Upotrijebit ćemo 4 zasebne aplikacije:

  • Autorizacijski poslužitelj - koji je središnji mehanizam provjere autentičnosti
  • Resursni poslužitelj - davatelj usluge Foos
  • Dvije klijentske aplikacije - aplikacije koje koriste SSO

Jednostavno rečeno, kada korisnik pokuša pristupiti resursu putem jedne klijentske aplikacije, bit će prvo preusmjeren na autentifikaciju putem Autorizacijskog poslužitelja. Keycloak će prijaviti korisnika i dok je još uvijek prijavljen u prvu aplikaciju, ako se drugoj klijentskoj aplikaciji pristupa putem istog preglednika, korisnik neće trebati ponovno unijeti svoje vjerodajnice.

Koristit ćemo Kod odobrenja odobri tip iz OAuth2 za pokretanje delegiranja provjere autentičnosti.

Koristit ćemo OAuth stog u Spring Security 5. Ako želite koristiti naslijeđeni stog Spring Security OAuth, pogledajte ovaj prethodni članak: Jednostavna jednokratna prijava s Spring Security OAuth2 (naslijeđeni stog)

Prema vodiču za migraciju:

Spring Security ovu značajku naziva OAuth 2.0 Login, a Spring Security OAuth SSO

Dobro, uskočimo odmah.

2. Poslužitelj za autorizaciju

Prije toga, Spring OAuth stog pružao je mogućnost postavljanja Autorizacijskog poslužitelja kao proljetne aplikacije.

Međutim, OAuth stog zastario je do proljeća i sada ćemo koristiti Keycloak kao naš autorizacijski poslužitelj.

Dakle, ovaj put postavit ćemo naš Autorizacijski poslužitelj kao ugrađeni Keycloak poslužitelj u aplikaciji Spring Boot.

U našoj predkonfiguraciji, definirat ćemo dva klijenta, ssoClient-1 i ssoClient-2, jedan za svaku prijavu klijenta.

3. Resursni poslužitelj

Dalje, trebamo Resource Server ili REST API koji će nam pružiti Foos će potrošiti naša klijentska aplikacija.

U osnovi je isto što smo i ranije koristili za naše kutne klijentske aplikacije.

4. Klijentske prijave

Pogledajmo sada našu klijentsku aplikaciju Thymeleaf; mi ćemo, naravno, koristiti Spring Boot da minimiziramo konfiguraciju.

Imajte to na umu trebat ćemo ih imati dva da bismo demonstrirali funkcionalnost jedinstvene prijave.

4.1. Ovisnosti Mavena

Prvo, trebat će nam sljedeće ovisnosti u našem pom.xml:

 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-oauth2-client org.springframework.boot spring-boot-starter-thymeleaf org.thymeleaf.extras thymeleaf-extras-springsecurity5 org. opružni okvir spring-webflux io.projectreactor.netty reactor-netty 

Samo da bismo dodali svu klijentsku podršku koja će nam biti potrebna, uključujući sigurnost spring-boot-starter-oauth2-client. Također, od starog RestTemplate bit će zastarjelo, koristit ćemo WebClient, i zato smo dodali proljeće-webtok i reaktor-mreža.

4.2. Konfiguracija sigurnosti

Sljedeći, najvažniji dio, sigurnosna konfiguracija naše prve klijentske aplikacije:

@EnableWebSecurity javna klasa UiSecurityConfig proširuje WebSecurityConfigurerAdapter {@Override javna void konfiguracija (HttpSecurity http) baca izuzetak {http.antMatcher ("/ **") .authorizeRequests () .antMatchers ("/") .permitAll. ovjeren () .and () .oauth2Login (); } @Bean WebClient webClient (ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository pooblastiliClientRepository) {ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = new ServletOAuth2AuthorizedClientEchangeRepositoryRepositoryRefaultory; oauth2.setDefaultOAuth2AuthorizedClient (true); vratiti WebClient.builder (). apply (oauth2.oauth2Configuration ()). build (); }}

Osnovni dio ove konfiguracije je oauth2Login () metoda koja se koristi za omogućavanje podrške za prijavu OAuth 2.0 za Spring Security. Budući da koristimo Keycloak, koji je prema zadanim postavkama rješenje za jedinstvenu prijavu za web aplikacije i RESTful web usluge, ne trebamo dodavati daljnju konfiguraciju za SSO.

Napokon smo definirali i a WebClient bean koji djeluje kao jednostavni HTTP klijent za obradu zahtjeva koji se šalju našem poslužitelju resursa.

I ovdje je primjena.iml:

spring: security: oauth2: client: registration: custom: client-id: ssoClient-1 client-secret: ssoClientSecret-1 doseg: čitanje, pisanje odobrenja-vrsta odobrenja: autorizacija_koda preusmjeravanje-uri: // localhost: 8082 / ui- one / login / oauth2 / code / custom provider: custom: auth-uri: // localhost: 8083 / auth / realms / baeldung / protocol / openid-connect / auth token-uri: // localhost: 8083 / auth / realms / baeldung / protocol / openid-connect / token user-info-uri: // localhost: 8083 / auth / realms / baeldung / protocol / openid-connect / userinfo user-name-attribute: prefer_username thymeleaf: cache: false server: port: 8082 servlet: context-path: / ui-one resourceserver: api: project: url: // localhost: 8081 / sso-resource-server / api / foos / 

Ovdje, proljeće.sigurnost.aauth2.klijent.registracija je korijenski prostor imena za registraciju klijenta. Klijenta smo definirali s registracijskim ID-om prilagođen. Tada smo definirali njegovo ID klijenta, klijent-tajna, opseg, vrsta odobrenja-odobrenje i preusmjeravanje-uri, što bi naravno trebalo biti isto kao ono definirano za naš autorizacijski poslužitelj.

Nakon toga definirali smo svog davatelja usluga ili Autorizacijski poslužitelj, opet s istim ID-om prilagođeni popisao njegove različite URI-je koje Spring Spring koristi. To je sve što trebamo definirati i framework čini čitav postupak prijave, uključujući preusmjeravanje na Keycloak, za nas neprimjetno.

Također imajte na umu da smo u ovom primjeru uveli naš Autorizacijski poslužitelj, ali naravno možemo koristiti i druge neovisne pružatelje usluga kao što su Facebook ili GitHub.

4.3. Kontroler

Zamijenimo sada naš kontroler u klijentskoj aplikaciji da tražimo Foos našeg poslužitelja resursa:

@Controller javna klasa FooClientController {@Value ("$ {resourceserver.api.url}") private String fooApiUrl; @Autowired privatni WebClient webClient; @GetMapping ("/ foos") javni niz getFoos (model modela) {Lista foos = this.webClient.get () .uri (fooApiUrl) .retrieve () .bodyToMono (nova ParameterizedTypeReference() { }) .blok(); model.addAttribute ("foos", foos); povratak "foos"; }}

Kao što vidimo, ovdje imamo samo jednu metodu koja će resurse poslati na foos predložak. Nismo morali dodati nikakav kôd za prijavu.

4.4. Prednji kraj

Sada, pogledajmo front-end konfiguraciju naše klijentske aplikacije. Ovdje se nećemo usredotočiti na to, uglavnom zato što smo to već pokrili na web mjestu.

Naša klijentska aplikacija ovdje ima vrlo jednostavan front-end; ovdje je index.html:

Proljetni OAuth klijent majčina dušica - 1 Dobrodošli!

Prijaviti se

I foos.html:

Proljetni OAuth klijent Thymeleaf -1 Zdravo, prefer_username 
iskaznicaIme
Nema foos
iskaznica Ime

The foos.html stranica treba provjeriti autentičnost korisnika. Ako neovlašteni korisnik pokuša pristupiti foos.html, prvo će biti preusmjereni na stranicu za prijavu Keycloaka.

4.5. Prijava drugog klijenta

Konfigurirat ćemo drugu aplikaciju, Proljetni klijent OAuth Thymeleaf -2 koristeći drugu client_idssoClient-2.

Uglavnom će biti isto kao i prva aplikacija koju smo upravo opisali.

The primjena.iml razlikovat će se i uključivat će različit client_id, client_secret i preusmjeriti_uri u svojoj spring.security.oauth2.client.registration:

spring: security: oauth2: client: registration: custom: client-id: ssoClient-2 client-secret: ssoClientSecret-2 opseg: čitanje, pisanje odobrenja-vrsta odobrenja: autorizacija_koda preusmjeravanje-uri: // localhost: 8084 / ui- dva / login / oauth2 / code / custom

I, naravno, trebamo imati drugačiji poslužiteljski priključak i za njega, kako bismo ih mogli paralelno pokretati:

poslužitelj: port: 8084 servlet: context-path: / ui-two

Konačno, dotjerat ćemo HTML-ove prednjeg kraja kako bi imali naslov kao Proljetni OAuth klijent majčina dušica - 2 umjesto – 1 tako da možemo razlikovati to dvoje.

5. Testiranje SSO ponašanja

Da testiramo SSO ponašanje, pokrenimo naše Aplikacije.

Trebat će nam sve naše 4 aplikacije za pokretanje - poslužitelj za autorizaciju, poslužitelj resursa i obje klijentske aplikacije - da bi bile pokrenute za ovo.

Otvorimo sada preglednik, recimo Chrome i prijavimo se Klijent-1 koristeći vjerodajnice [e-pošta zaštićena] / 123. Zatim u drugom prozoru ili kartici pritisnite URL za Klijent-2. Klikom na gumb za prijavu bit ćemo preusmjereni na Foos stranicu odmah, zaobilazeći korak provjere autentičnosti.

Slično tome, ako se korisnik prijavi u Klijent-2 prvo, ne trebaju unijeti svoje korisničko ime / lozinku za Klijent-1.

6. Zaključak

U ovom smo se vodiču usredotočili na implementaciju jedinstvene prijave pomoću Spring Security OAuth2 i Spring Boot koristeći Keycloak kao pružatelja identiteta.

Kao i uvijek, puni izvorni kod možete pronaći na GitHubu.