Spring Security: Udforskning af JDBC-godkendelse

Udholdenhedstop

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Oversigt

I denne korte vejledning undersøger vi de muligheder, som Spring tilbyder til at udføre JDBC-godkendelse ved hjælp af en eksisterende Datakilde konfiguration.

I vores godkendelse med et databasestøttet UserDetailsService-indlæg analyserede vi en tilgang for at opnå dette ved at implementere UserDetailService grænseflade os selv.

Denne gang bruger vi AuthenticationManagerBuilder # jdbcAuthentication direktiv om at analysere fordele og ulemper ved denne enklere tilgang.

2. Brug af en indbygget H2-forbindelse

Først og fremmest analyserer vi, hvordan vi kan opnå godkendelse ved hjælp af en indbygget H2-database.

Dette er let at opnå, fordi det meste af Spring Boot's autokonfiguration er klargjort direkte til dette scenarie.

2.1. Afhængigheder og databasekonfiguration

Lad os starte med at følge instruktionerne i vores forrige Spring Boot With H2 Database-indlæg til:

  1. Inkluder det tilsvarende spring-boot-starter-data-jpa og h2 afhængigheder
  2. Konfigurer databaseforbindelsen med applikationsegenskaber
  3. Aktivér H2-konsollen

2.2. Konfiguration af JDBC-godkendelse

Vi bruger Spring Security's AuthenticationManagerBuilder konfigurationshjælper til at konfigurere JDBC-godkendelse:

@Autowired privat DataSource dataSource; @Autowired public void configureGlobal (AuthenticationManagerBuilder auth) kaster undtagelse {auth.jdbcAuthentication () .dataSource (dataSource) .withDefaultSchema () .withUser (User.withUsername ("user") .password (passwordEncoder ().). Encode ("password") ) .roles ("BRUGER")); } @Bean public PasswordEncoder passwordEncoder () {returner ny BCryptPasswordEncoder (); }

Som vi kan se, bruger vi den autokonfigurerede Datakilde. Det medDefaultSchema direktivet tilføjer et databasescript, der udfylder standardskemaet, så brugere og myndigheder kan lagres.

Dette grundlæggende brugerskema er dokumenteret i Spring Security Appendix.

Endelig opretter vi en post i databasen med en standardbruger programmatisk.

2.3. Bekræftelse af konfigurationen

Lad os oprette et meget simpelt slutpunkt for at hente det godkendte Rektor Information:

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

Derudover vil vi sikre dette slutpunkt, mens vi giver adgang til H2-konsollen:

@Configuration offentlig klasse SecurityConfiguration udvider WebSecurityConfigurerAdapter {@Override beskyttet ugyldig konfiguration (HttpSecurity httpSecurity) kaster undtagelse {httpSecurity.authorizeRequests () .antMatchers ("/ h2-console / **") .permitAll () .anyRequesticated) .a. .og () .formLogin (); httpSecurity.csrf () .ignoringAntMatchers ("/ h2-konsol / **"); httpSecurity.headers () .frameOptions () .sameOrigin (); }}

Bemærk: her gengiver vi den tidligere sikkerhedskonfiguration implementeret af Spring Boot, men i et virkeligt scenarie vil vi sandsynligvis slet ikke aktivere H2-konsollen.

Nu kører vi applikationen og gennemser H2-konsollen. Vi kan bekræfte det Spring opretter to tabeller i vores indlejrede database: brugere og myndigheder.

Deres struktur svarer til den struktur, der er defineret i Spring Security Appendix, vi nævnte før.

Lad os endelig godkende og anmode om /rektor slutpunkt for at se de relaterede oplysninger, herunder brugeroplysningerne.

2.4. Under kølerhjelmen

I begyndelsen af ​​dette indlæg præsenterede vi et link til en tutorial, der forklarede hvordan vi kan tilpasse databasestøttet godkendelse ved at implementere UserDetailsService interface; Vi anbefaler kraftigt at se på dette indlæg, hvis vi vil forstå, hvordan ting fungerer under emhætten.

I dette tilfælde stoler vi på en implementering af den samme grænseflade leveret af Spring Security; det JdbcDaoImpl.

Hvis vi udforsker denne klasse, ser vi UserDetails implementering, den bruger, og mekanismerne til at hente brugeroplysninger fra databasen.

Dette fungerer ret godt i dette enkle scenario, men det har nogle ulemper, hvis vi vil tilpasse databaseskemaet, eller endda hvis vi vil bruge en anden databaseleverandør.

Lad os se, hvad der sker, hvis vi ændrer konfigurationen til at bruge en anden JDBC-tjeneste.

3. Tilpasning af skemaet til en anden database

I dette afsnit konfigurerer vi godkendelse på vores projekt ved hjælp af en MySQL-database.

Som vi ser næste, skal vi undgå at bruge standardskemaet og give vores eget for at opnå dette.

3.1. Afhængigheder og databasekonfiguration

Lad os for det første fjerne h2 afhængighed og udskift den for det tilsvarende MySQL-bibliotek:

 mysql mysql-connector-java 8.0.17 

Som altid kan vi slå den nyeste version af biblioteket i Maven Central op.

Lad os nu genindstille applikationsegenskaberne i overensstemmelse hermed:

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

3.2. Kørsel af standardkonfiguration

Selvfølgelig skal disse tilpasses til at oprette forbindelse til din kørende MySQL-server. Til testformål starter vi her en ny forekomst ved hjælp af Docker:

docker køre -p 3306: 3306 --navn bael-mysql -e MYSQL_ROOT_PASSWORD = pass -e MYSQL_DATABASE = jdbc_authentication mysql: seneste

Lad os køre projektet nu for at se, om standardkonfigurationen er egnet til en MySQL-database.

Faktisk kan applikationen ikke komme i gang på grund af en SQLSyntaxErrorException. Dette giver faktisk mening; som vi sagde, det meste af standard autokonfiguration er egnet til en HSQLDB.

I dette tilfælde, DDL-scriptet leveret med medDefaultSchema direktivet bruger en dialekt, der ikke er egnet til MySQL.

Derfor er vi nødt til at undgå at bruge dette skema og give vores eget.

3.3. Tilpasning af godkendelseskonfigurationen

Da vi ikke vil bruge standardskemaet, bliver vi nødt til at fjerne den korrekte erklæring fra AuthenticationManagerBuilder konfiguration.

Da vi leverer vores egne SQL-scripts, kan vi også undgå at prøve at oprette brugeren programmatisk:

@Autowired public void configureGlobal (AuthenticationManagerBuilder auth) kaster undtagelse {auth.jdbcAuthentication () .dataSource (dataSource); }

Lad os nu se på database initialiserings scripts.

Først vores skema.sql:

Opret TABLE-brugere (brugernavn VARCHAR (50) IKKE NULL, adgangskode VARCHAR (100) IKKE NULL, aktiveret TINYINT IKKE NULL STANDARD 1, PRIMÆR NØGLE (brugernavn)); OPRET TABELmyndigheder (brugernavn VARCHAR (50) IKKE NULL, myndighed VARCHAR (50) IKKE NULL, UDENLANDSK KEY (brugernavn) REFERENCER brugere (brugernavn)); OPRET UNIK INDEKS ix_auth_username på autoriteter (brugernavn, autoritet);

Og så vores data.sql:

- Brugerbruger / videregiv INSERT INTO-brugere (brugernavn, adgangskode, aktiveret) værdier ('bruger', '$ 2a $ 10 $ 8.UnVuG9HHgffUDAlk8qfOuVGkqRzgVymGe07xd00DMxs.AQubh4a', 1); INDSÆT I autoriteter (brugernavn, autoritet) værdier ('bruger', 'ROLE_USER');

Endelig skal vi ændre nogle andre applikationsegenskaber:

  • Da vi ikke forventer, at dvaletilstand opretter skemaet nu, bør vi deaktivere ddl-auto ejendom
  • Spring Boot initialiserer som standard kun datakilden til indlejrede databaser, hvilket ikke er tilfældet her:
spring.datasource.initialization-mode = altid spring.jpa.hibernate.ddl-auto = ingen

Som et resultat skal vi nu være i stand til at starte vores applikation korrekt, godkende og hente Rektor data fra slutpunktet.

4. Tilpasning af forespørgsler til et andet skema

Lad os gå et skridt videre. Forestil dig, at standardskemaet bare ikke passer til vores behov.

4.1. Ændring af standardskemaet

Forestil dig for eksempel, at vi allerede har en database med en struktur, der adskiller sig lidt fra den standard:

Opret TABEL bael_users (navn VARCHAR (50) NOT NULL, email VARCHAR (50) NOT NULL, password VARCHAR (100) NOT NULL, enabled TINYINT NOT NULL DEFAULT 1, PRIMARY KEY (email)); OPRET TABELmyndigheder (e-mail VARCHAR (50) IKKE NULL, myndighed VARCHAR (50) IKKE NULL, UDENLANDSK Nøgle (e-mail) REFERENCER bael_users (e-mail)); OPRET UNIK INDEKS ix_auth_email til myndigheder (e-mail, autoritet);

Endelig vores data.sql script vil også blive tilpasset denne ændring:

- Bruger [e-mailbeskyttet] / videregiv INDSÆT TIL bael_users (navn, e-mail, adgangskode, aktiveret) værdier ('bruger', '[e-mail-beskyttet]', '$ 2a $ 10 $ 8.UnVuG9HHgffUDAlk8qfOuVGkqRzgVymGe07xd00DMxs.AQubh4a', 1); INDSÆT I autoriteter (e-mail, autoritet) værdier ('[email protected]', 'ROLE_USER');

4.2. Kørsel af applikationen med det nye skema

Lad os starte vores applikation. Det initialiseres korrekt, hvilket giver mening, da vores skema er korrekt.

Nu, hvis vi prøver at logge ind, finder vi, at der bliver bedt om en fejl, når vi præsenterer legitimationsoplysningerne.

Spring Security er stadig på udkig efter en brugernavn felt i databasen. Heldig for os giver JDBC-godkendelseskonfigurationen muligheden for tilpasning af de forespørgsler, der bruges til at hente brugeroplysninger i godkendelsesprocessen.

4.3. Tilpasning af søgeforespørgsler

Det er ret nemt at tilpasse forespørgslerne. Vi er simpelthen nødt til at levere vores egne SQL-sætninger, når vi konfigurerer AuthenticationManagerBuilder:

@Autowired public void configureGlobal (AuthenticationManagerBuilder auth) kaster undtagelse {auth.jdbcAuthentication () .dataSource (dataSource) .usersByUsernameQuery ("vælg e-mail, adgangskode, aktiveret" + "fra bael_users" + "hvor e-mail =?") .AuthoritiesByUs. vælg e-mail, autoritet "+" fra myndigheder "+" hvor e-mail =? "); }

Vi kan starte applikationen igen og få adgang til /rektor slutpunkt ved hjælp af de nye legitimationsoplysninger.

5. Konklusion

Som vi kan se, er denne tilgang meget enklere end at skulle skabe vores egen UserDetailServiceimplementering, hvilket indebærer en hård proces; oprettelse af enheder og klasser, der implementerer UserDetail interface og tilføjelse af arkiver til vores projekt.

Ulempen er naturligvis den lille fleksibilitet, den giver, når vores database eller vores logik adskiller sig fra standardstrategien leveret af Spring Security-løsningen.

Endelig kan vi se på de komplette eksempler i vores GitHub-arkiv. Vi inkluderede endda et eksempel ved hjælp af PostgreSQL, som vi ikke viste i denne vejledning, bare for at holde tingene enkle.

Persistens bund

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN