Proljetna sigurnost: istraživanje JDBC provjere autentičnosti

Vrh postojanosti

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ

1. Pregled

U ovom kratkom vodiču istražit ćemo mogućnosti koje nudi Spring za izvođenje JDBC provjere autentičnosti koristeći postojeću Izvor podataka konfiguracija.

U našoj provjeri autentičnosti s postom UserDetailsService koji podržava baza podataka, analizirali smo jedan pristup kako bismo to postigli, primjenom UserDetailService sučeljemo se.

Ovaj put ćemo se poslužiti AuthenticationManagerBuilder # jdbcAuthentication smjernica za analizu prednosti i nedostataka ovog jednostavnijeg pristupa.

2. Korištenje ugrađene H2 veze

Prije svega, analizirat ćemo kako možemo postići provjeru autentičnosti pomoću ugrađene H2 baze podataka.

To je lako postići jer je većina autokonfiguracije Spring Boota spremna za ovaj scenarij.

2.1. Ovisnosti i konfiguracija baze podataka

Krenimo slijedeći upute iz prethodnog posta Spring Boot With H2 Database:

  1. Uključite odgovarajuće spring-boot-starter-data-jpa i h2 ovisnosti
  2. Konfigurirajte vezu baze podataka s svojstvima aplikacije
  3. Omogućite H2 konzolu

2.2. Konfiguriranje JDBC autentifikacije

Koristit ćemo Spring Security's AuthenticationManagerBuilder pomoćnik za konfiguraciju za konfiguriranje JDBC provjere autentičnosti:

@Autowired privatni DataSource dataSource; @Autowired javna praznina configureGlobal (AuthenticationManagerBuilder auth) baca izuzetak {auth.jdbcAuthentication () .dataSource (dataSource) .withDefaultSchema () .withUser (User.withUsername ("user") .password (passwordEncoder (). ) .roles ("KORISNIK")); } @Bean public PasswordEncoder passwordEncoder () {return new BCryptPasswordEncoder (); }

Kao što vidimo, koristimo se automatski konfiguriranim Izvor podataka. The withDefaultSchema Direktiva dodaje skriptu baze podataka koja će popuniti zadanu shemu, omogućujući pohranu korisnika i ovlasti.

Ova osnovna korisnička shema dokumentirana je u Proljetnom sigurnosnom dodatku.

Konačno, programski izrađujemo unos u bazi podataka sa zadanim korisnikom.

2.3. Provjera konfiguracije

Stvorimo vrlo jednostavnu krajnju točku za dohvat ovjerenog Glavni informacija:

@RestController @RequestMapping ("/ principal") javna klasa UserController {@GetMapping public Principal retrievePrincipal (Principal principal) {return principal; }}

Uz to, osigurat ćemo i ovu krajnju točku, istovremeno dopuštajući pristup H2 konzoli:

@Configuration javna klasa SecurityConfiguration proširuje WebSecurityConfigurerAdapter {@ Override zaštićena void konfiguracija (HttpSecurity httpSecurity) baca izuzetak {httpSecurity.authorizeRequests () .antMatchers ("/ h2-console / **") .permitAll () .anyRequest () .anyRequest (All). .and () .formLogin (); httpSecurity.csrf () .ignoringAntMatchers ("/ h2-console / **"); httpSecurity.headers () .frameOptions () .sameOrigin (); }}

Napomena: ovdje reproduciramo bivšu sigurnosnu konfiguraciju koju je implementirao Spring Boot, ali u scenariju iz stvarnog života vjerojatno uopće nećemo omogućiti H2 konzolu.

Sada ćemo pokrenuti aplikaciju i pregledavati H2 konzolu. To možemo provjeriti Spring stvara dvije tablice u našoj ugrađenoj bazi podataka: korisnika i vlasti.

Njihova struktura odgovara strukturi definiranoj u Proljetnom sigurnosnom dodatku koji smo prije spomenuli.

Na kraju, provjerimo autentičnost i zatražimo /glavni krajnju točku da biste vidjeli povezane informacije, uključujući korisničke pojedinosti.

2.4. Ispod haube

Na početku ovog posta predstavili smo vezu do vodiča koji je objasnio kako možemo prilagoditi provjeru autentičnosti podržane bazom podataka implementirajući UserDetailsService sučelje; toplo preporučujemo da pogledate taj post ako želimo razumjeti kako stvari funkcioniraju ispod haube.

U ovom se slučaju oslanjamo na implementaciju istog sučelja koje pruža Spring Security; the JdbcDaoImpl.

Ako istražimo ovaj razred, vidjet ćemo Pojedinosti o korisniku implementaciju koju koristi i mehanizme za dohvaćanje korisničkih podataka iz baze podataka.

To prilično dobro funkcionira za ovaj jednostavan scenarij, ali ima neke nedostatke ako želimo prilagoditi shemu baze podataka ili čak ako želimo koristiti drugog dobavljača baze podataka.

Pogledajmo što će se dogoditi ako promijenimo konfiguraciju da koristi drugu JDBC uslugu.

3. Prilagođavanje sheme za drugu bazu podataka

U ovom ćemo odjeljku konfigurirati provjeru autentičnosti na našem projektu pomoću MySQL baze podataka.

Kao što ćemo vidjeti sljedeće, da bismo to postigli, morat ćemo izbjeći korištenje zadane sheme i pružiti vlastitu.

3.1. Ovisnosti i konfiguracija baze podataka

Za početak, uklonimo h2 ovisnost i zamijenite je za odgovarajuću MySQL knjižnicu:

 mysql mysql-konektor-java 8.0.17 

Kao i uvijek, možemo potražiti najnoviju verziju knjižnice u Maven Central.

Sada ponovo postavimo svojstva aplikacije u skladu s tim:

spring.datasource.url = jdbc: mysql: // localhost: 3306 / jdbc_authentication spring.datasource.username = root spring.datasource.password = pass

3.2. Pokretanje zadane konfiguracije

Naravno, ovo bi trebalo prilagoditi povezivanju s vašim MySQL poslužiteljem. Za potrebe testiranja, ovdje ćemo pokrenuti novu instancu pomoću Dockera:

docker pokreni -p 3306: 3306 --name bael-mysql -e MYSQL_ROOT_PASSWORD = pass -e MYSQL_DATABASE = jdbc_authentication mysql: najnoviji

Pokrenimo projekt sada da vidimo je li zadana konfiguracija prikladna za MySQL bazu podataka.

Zapravo, aplikacija neće moći započeti zbog SQLSyntaxErrorException. Ovo zapravo ima smisla; kao što smo rekli, većina zadane automatske konfiguracije prikladna je za HSQLDB.

U ovom slučaju, DDL skripta isporučena s withDefaultSchema direktiva koristi dijalekt koji nije prikladan za MySQL.

Stoga moramo izbjegavati korištenje ove sheme i pružiti vlastitu.

3.3. Prilagođavanje konfiguracije provjere autentičnosti

Kako ne želimo koristiti zadanu shemu, morat ćemo ukloniti odgovarajuću izjavu iz datoteke AuthenticationManagerBuilder konfiguracija.

Također, budući da ćemo pružiti vlastite SQL skripte, možemo izbjeći pokušaj programskog stvaranja korisnika:

@Autowired javna praznina configureGlobal (AuthenticationManagerBuilder auth) baca iznimku {auth.jdbcAuthentication () .dataSource (dataSource); }

Sada ćemo pogledati skripte za inicijalizaciju baze podataka.

Prvo, naš shema.sql:

IZRADI TABELU korisnika (korisničko ime VARCHAR (50) NOT NULL, lozinka VARCHAR (100) NOT NULL, omogućeno TINYINT NOT NULL DEFAULT 1, OSNOVNI KLJUČ (korisničko ime)); ORGANI ZA STVARANJE TABELE (korisničko ime VARCHAR (50) NIJE NULL, ovlaštenje VARCHAR (50) NIJE NULL, STRANI KLJUČ (korisničko ime) REFERENCE korisnici (korisničko ime)); STVARI JEDINSTVENI INDEKS ix_auth_username na ovlastima (korisničko ime, ovlaštenje);

A onda, naš podaci.sql:

- Korisnik korisnik / proslijedi INSERT INTO korisnicima (korisničko ime, lozinka, omogućeno) vrijednosti ('user', '$ 2a $ 10 $ 8.UnVuG9HHgffUDAlk8qfOuVGkqRzgVymGe07xd00DMxs.AQubh4a', 1); INSERT INTO ovlasti (korisničko ime, ovlaštenje) vrijednosti ('korisnik', 'ROLE_USER');

Konačno, trebali bismo izmijeniti neka druga svojstva aplikacije:

  • Budući da ne očekujemo da će Hibernate stvoriti shemu sada, trebali bismo onemogućiti ddl-auto imovine
  • Prema zadanim postavkama Spring Boot inicijalizira izvor podataka samo za ugrađene baze podataka, što ovdje nije slučaj:
spring.datasource.initialization-mode = always spring.jpa.hibernate.ddl-auto = none

Kao rezultat toga, sada bismo trebali moći pravilno pokrenuti našu aplikaciju, autentificirati i dohvatiti Glavni podaci od krajnje točke.

4. Prilagođavanje upita za drugu shemu

Idemo korak dalje. Zamislite da zadana shema jednostavno nije prikladna za naše potrebe.

4.1. Promjena zadane sheme

Zamislite, na primjer, da već imamo bazu podataka sa strukturom koja se malo razlikuje od zadane:

IZRADI TABELU bael_users (ime VARCHAR (50) NIJE NULL, e-pošta VARCHAR (50) NIJE NULL, lozinka VARCHAR (100) NIJE NULL, omogućeno TINYINT NOT NULL DEFAULT 1, PRIMARNI KLJUČ (e-pošta)); STVORITE ovlaštenja za TABELU (e-pošta VARCHAR (50) NIJE NULL, ovlaštenje VARCHAR (50) NIJE NULL, STRANI KLJUČ (e-pošta) REFERENCE bael_users (e-pošta)); IZRADI JEDINSTVENI INDEKS ix_auth_email o tijelima (e-mail, autoritet);

Napokon, naša podaci.sql skripta će se prilagoditi i ovoj promjeni:

- Korisnik [zaštićen e-poštom] / proslijedi INSERT INTO bael_users (ime, e-pošta, lozinka, omogućeno) vrijednosti ('user', '[email protected]', '$ 2a $ 10 $ 8.UnVuG9HHgffUDAlk8qfOuVGkqRzgVymGe07xd00DMxs.AQubh4a', 1); INSERT INTO ovlasti (e-pošta, ovlaštenje) vrijednosti ('[zaštićena e-poštom]', 'ROLE_USER');

4.2. Pokretanje aplikacije s novom shemom

Pokrenimo našu aplikaciju. Pravilno se inicijalizira, što ima smisla jer je naša shema točna.

Ako se sada pokušamo prijaviti, ustanovit ćemo da se prilikom predstavljanja vjerodajnica traži pogreška.

Spring Security još uvijek traži Korisničko ime polje u bazi podataka. Srećom po nas, konfiguracija JDBC provjere autentičnosti nudi mogućnost prilagođavanje upita koji se koriste za pronalaženje korisničkih podataka u postupku provjere autentičnosti.

4.3. Prilagođavanje upita za pretraživanje

Prilagođavanje upita prilično je jednostavno. Jednostavno moramo pružiti vlastite SQL izjave prilikom konfiguriranja AuthenticationManagerBuilder:

@Autowired javna void configureGlobal (AuthenticationManagerBuilder auth) baca Iznimku {auth.jdbcAuthentication () .dataSource (dataSource) .usersByUsernameQuery ("select email, password, enabled" + "from bael_users" + "where email =?") .Authorityu odaberite e-poštu, ovlaštenje "+" od nadležnih tijela "+" gdje je adresa e-pošte??); }

Možemo još jednom pokrenuti aplikaciju i pristupiti joj /glavni krajnju točku pomoću novih vjerodajnica.

5. Zaključak

Kao što vidimo, ovaj je pristup puno jednostavniji od stvaranja vlastitog UserDetailServiceprovedba, koja podrazumijeva naporan proces; stvaranje entiteta i klasa koji implementiraju UserDetail sučelje i dodavanje spremišta u naš projekt.

Nedostatak je, naravno, mala fleksibilnost koju nudi kada se naša baza podataka ili naša logika razlikuje od zadane strategije koje pruža rješenje Spring Security.

Na kraju, možemo pogledati cjelovite primjere u našem GitHub spremištu. Uključili smo čak i primjer korištenja PostgreSQL-a koji nismo prikazali u ovom vodiču, samo da pojednostavimo stvari.

Dno postojanosti

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ

$config[zx-auto] not found$config[zx-overlay] not found